Merge "Fix stale View tracking in ShadeViewDiffer" into tm-dev
diff --git a/Android.bp b/Android.bp
index 753cefc..149b223 100644
--- a/Android.bp
+++ b/Android.bp
@@ -97,6 +97,7 @@
":platform-compat-native-aidl",
// AIDL sources from external directories
+ ":android.hardware.gnss-V2-java-source",
":android.hardware.graphics.common-V3-java-source",
":android.hardware.security.keymint-V2-java-source",
":android.hardware.security.secureclock-V1-java-source",
@@ -328,6 +329,7 @@
"modules-utils-preconditions",
"modules-utils-synchronous-result-receiver",
"modules-utils-os",
+ "modules-utils-uieventlogger-interface",
"framework-permission-aidl-java",
"spatializer-aidl-java",
"audiopolicy-types-aidl-java",
diff --git a/apct-tests/perftests/windowmanager/src/android/wm/RelayoutPerfTest.java b/apct-tests/perftests/windowmanager/src/android/wm/RelayoutPerfTest.java
index 4ad015d..c92c634 100644
--- a/apct-tests/perftests/windowmanager/src/android/wm/RelayoutPerfTest.java
+++ b/apct-tests/perftests/windowmanager/src/android/wm/RelayoutPerfTest.java
@@ -20,6 +20,7 @@
import android.app.Activity;
import android.content.Context;
+import android.os.Bundle;
import android.os.RemoteException;
import android.perftests.utils.BenchmarkState;
import android.perftests.utils.PerfStatusReporter;
@@ -153,7 +154,8 @@
while (state.keepRunning()) {
session.relayout(mWindow, mParams, mWidth, mHeight,
mViewVisibility.getAsInt(), mFlags, mOutFrames,
- mOutMergedConfiguration, mOutSurfaceControl, mOutInsetsState, mOutControls);
+ mOutMergedConfiguration, mOutSurfaceControl, mOutInsetsState, mOutControls,
+ new Bundle());
}
}
}
diff --git a/apex/jobscheduler/framework/java/com/android/server/usage/AppStandbyInternal.java b/apex/jobscheduler/framework/java/com/android/server/usage/AppStandbyInternal.java
index e2426c2..f822a18 100644
--- a/apex/jobscheduler/framework/java/com/android/server/usage/AppStandbyInternal.java
+++ b/apex/jobscheduler/framework/java/com/android/server/usage/AppStandbyInternal.java
@@ -2,6 +2,7 @@
import android.annotation.CurrentTimeMillisLong;
import android.annotation.NonNull;
+import android.annotation.Nullable;
import android.annotation.UserIdInt;
import android.app.ActivityManager.ProcessState;
import android.app.usage.AppStandbyInfo;
@@ -237,4 +238,11 @@
*/
@ProcessState
int getBroadcastResponseFgThresholdState();
+
+ /**
+ * Return the last known value corresponding to the {@code key} from
+ * {@link android.provider.DeviceConfig#NAMESPACE_APP_STANDBY} in AppStandbyController.
+ */
+ @Nullable
+ String getAppStandbyConstant(@NonNull String key);
}
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 90ec700..528be3c 100644
--- a/apex/jobscheduler/service/java/com/android/server/alarm/AlarmManagerService.java
+++ b/apex/jobscheduler/service/java/com/android/server/alarm/AlarmManagerService.java
@@ -4891,13 +4891,15 @@
filter.addAction(Intent.ACTION_PACKAGE_RESTARTED);
filter.addAction(Intent.ACTION_QUERY_PACKAGE_RESTART);
filter.addDataScheme(IntentFilter.SCHEME_PACKAGE);
- getContext().registerReceiver(this, filter);
+ getContext().registerReceiverForAllUsers(this, filter,
+ /* broadcastPermission */ null, /* scheduler */ null);
// Register for events related to sdcard installation.
IntentFilter sdFilter = new IntentFilter();
sdFilter.addAction(Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE);
sdFilter.addAction(Intent.ACTION_USER_STOPPED);
sdFilter.addAction(Intent.ACTION_UID_REMOVED);
- getContext().registerReceiver(this, sdFilter);
+ getContext().registerReceiverForAllUsers(this, sdFilter,
+ /* broadcastPermission */ null, /* scheduler */ null);
}
@Override
@@ -4915,9 +4917,6 @@
}
}
return;
- case Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE:
- pkgList = intent.getStringArrayExtra(Intent.EXTRA_CHANGED_PACKAGE_LIST);
- break;
case Intent.ACTION_USER_STOPPED:
final int userHandle = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, -1);
if (userHandle >= 0) {
@@ -4932,6 +4931,18 @@
mRemovalHistory.delete(uid);
mLastOpScheduleExactAlarm.delete(uid);
return;
+ case Intent.ACTION_PACKAGE_ADDED:
+ if (intent.getBooleanExtra(Intent.EXTRA_REPLACING, false)) {
+ final String packageUpdated = intent.getData().getSchemeSpecificPart();
+ mHandler.obtainMessage(
+ AlarmHandler.CHECK_EXACT_ALARM_PERMISSION_ON_UPDATE, uid, -1,
+ packageUpdated).sendToTarget();
+ }
+ mHandler.sendEmptyMessage(AlarmHandler.REFRESH_EXACT_ALARM_CANDIDATES);
+ return;
+ case Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE:
+ pkgList = intent.getStringArrayExtra(Intent.EXTRA_CHANGED_PACKAGE_LIST);
+ break;
case Intent.ACTION_PACKAGE_REMOVED:
if (intent.getBooleanExtra(Intent.EXTRA_REPLACING, false)) {
// This package is being updated; don't kill its alarms.
@@ -4950,15 +4961,6 @@
}
}
break;
- case Intent.ACTION_PACKAGE_ADDED:
- if (intent.getBooleanExtra(Intent.EXTRA_REPLACING, false)) {
- final String packageUpdated = intent.getData().getSchemeSpecificPart();
- mHandler.obtainMessage(
- AlarmHandler.CHECK_EXACT_ALARM_PERMISSION_ON_UPDATE, uid, -1,
- packageUpdated).sendToTarget();
- }
- mHandler.sendEmptyMessage(AlarmHandler.REFRESH_EXACT_ALARM_CANDIDATES);
- return;
}
if (pkgList != null && (pkgList.length > 0)) {
for (String pkg : pkgList) {
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 18f63b7..23056b5 100644
--- a/apex/jobscheduler/service/java/com/android/server/job/JobConcurrencyManager.java
+++ b/apex/jobscheduler/service/java/com/android/server/job/JobConcurrencyManager.java
@@ -17,6 +17,7 @@
package com.android.server.job;
import static com.android.server.job.JobSchedulerService.MAX_JOB_CONTEXTS_COUNT;
+import static com.android.server.job.JobSchedulerService.RESTRICTED_INDEX;
import static com.android.server.job.JobSchedulerService.sElapsedRealtimeClock;
import android.annotation.IntDef;
@@ -32,9 +33,11 @@
import android.content.Intent;
import android.content.IntentFilter;
import android.content.pm.UserInfo;
+import android.os.BatteryStats;
import android.os.Handler;
import android.os.PowerManager;
import android.os.RemoteException;
+import android.os.ServiceManager;
import android.os.UserHandle;
import android.provider.DeviceConfig;
import android.util.ArraySet;
@@ -51,19 +54,24 @@
import com.android.internal.R;
import com.android.internal.annotations.GuardedBy;
import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.app.IBatteryStats;
import com.android.internal.app.procstats.ProcessStats;
import com.android.internal.util.StatLogger;
import com.android.server.JobSchedulerBackgroundThread;
import com.android.server.LocalServices;
import com.android.server.job.controllers.JobStatus;
import com.android.server.job.controllers.StateController;
+import com.android.server.job.restrictions.JobRestriction;
import com.android.server.pm.UserManagerInternal;
+import java.io.PrintWriter;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
+import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.function.Consumer;
+import java.util.function.Predicate;
/**
* This class decides, given the various configuration and the system status, which jobs can start
@@ -278,6 +286,11 @@
String[] mRecycledShouldStopJobReason = new String[MAX_JOB_CONTEXTS_COUNT];
+ /**
+ * Set of JobServiceContexts that we use to run jobs.
+ */
+ final List<JobServiceContext> mActiveServices = new ArrayList<>();
+
private final ArraySet<JobStatus> mRunningJobs = new ArraySet<>();
private final WorkCountTracker mWorkCountTracker = new WorkCountTracker();
@@ -358,6 +371,20 @@
onInteractiveStateChanged(mPowerManager.isInteractive());
}
+ /**
+ * Called when the boot phase reaches
+ * {@link com.android.server.SystemService#PHASE_THIRD_PARTY_APPS_CAN_START}.
+ */
+ void onThirdPartyAppsCanStart() {
+ final IBatteryStats batteryStats = IBatteryStats.Stub.asInterface(
+ ServiceManager.getService(BatteryStats.SERVICE_NAME));
+ for (int i = 0; i < MAX_JOB_CONTEXTS_COUNT; i++) {
+ mActiveServices.add(
+ new JobServiceContext(mService, this, batteryStats,
+ mService.mJobPackageTracker, mContext.getMainLooper()));
+ }
+ }
+
@GuardedBy("mLock")
void onAppRemovedLocked(String pkgName, int uid) {
final PackageStats packageStats = mActivePkgStats.get(UserHandle.getUserId(uid), pkgName);
@@ -390,6 +417,7 @@
case PowerManager.ACTION_DEVICE_IDLE_MODE_CHANGED:
if (mPowerManager != null && mPowerManager.isDeviceIdleMode()) {
synchronized (mLock) {
+ stopUnexemptedJobsForDoze();
stopLongRunningJobsLocked("deep doze");
}
}
@@ -471,6 +499,11 @@
}
@GuardedBy("mLock")
+ ArraySet<JobStatus> getRunningJobsLocked() {
+ return mRunningJobs;
+ }
+
+ @GuardedBy("mLock")
boolean isJobRunningLocked(JobStatus job) {
return mRunningJobs.contains(job);
}
@@ -546,7 +579,7 @@
}
final List<JobStatus> pendingJobs = mService.mPendingJobs;
- final List<JobServiceContext> activeServices = mService.mActiveServices;
+ final List<JobServiceContext> activeServices = mActiveServices;
// To avoid GC churn, we recycle the arrays.
JobStatus[] contextIdToJobMap = mRecycledAssignContextIdToJobMap;
@@ -719,9 +752,44 @@
}
@GuardedBy("mLock")
+ boolean stopJobOnServiceContextLocked(JobStatus job,
+ @JobParameters.StopReason int reason, int internalReasonCode, String debugReason) {
+ if (!mRunningJobs.contains(job)) {
+ return false;
+ }
+
+ for (int i = 0; i < mActiveServices.size(); i++) {
+ JobServiceContext jsc = mActiveServices.get(i);
+ final JobStatus executing = jsc.getRunningJobLocked();
+ if (executing != null && executing.matches(job.getUid(), job.getJobId())) {
+ jsc.cancelExecutingJobLocked(reason, internalReasonCode, debugReason);
+ return true;
+ }
+ }
+ Slog.wtf(TAG, "Couldn't find running job on a context");
+ mRunningJobs.remove(job);
+ return false;
+ }
+
+ @GuardedBy("mLock")
+ private void stopUnexemptedJobsForDoze() {
+ // When becoming idle, make sure no jobs are actively running,
+ // except those using the idle exemption flag.
+ for (int i = 0; i < mActiveServices.size(); i++) {
+ JobServiceContext jsc = mActiveServices.get(i);
+ final JobStatus executing = jsc.getRunningJobLocked();
+ if (executing != null && !executing.canRunInDoze()) {
+ jsc.cancelExecutingJobLocked(JobParameters.STOP_REASON_DEVICE_STATE,
+ JobParameters.INTERNAL_STOP_REASON_DEVICE_IDLE,
+ "cancelled due to doze");
+ }
+ }
+ }
+
+ @GuardedBy("mLock")
private void stopLongRunningJobsLocked(@NonNull String debugReason) {
for (int i = 0; i < MAX_JOB_CONTEXTS_COUNT; ++i) {
- final JobServiceContext jsc = mService.mActiveServices.get(i);
+ final JobServiceContext jsc = mActiveServices.get(i);
final JobStatus jobStatus = jsc.getRunningJobLocked();
if (jobStatus != null && !jsc.isWithinExecutionGuaranteeTime()) {
@@ -731,6 +799,41 @@
}
}
+ @GuardedBy("mLock")
+ void stopNonReadyActiveJobsLocked() {
+ for (int i = 0; i < mActiveServices.size(); i++) {
+ JobServiceContext serviceContext = mActiveServices.get(i);
+ final JobStatus running = serviceContext.getRunningJobLocked();
+ if (running == null) {
+ continue;
+ }
+ if (!running.isReady()) {
+ if (running.getEffectiveStandbyBucket() == RESTRICTED_INDEX
+ && running.getStopReason() == JobParameters.STOP_REASON_APP_STANDBY) {
+ serviceContext.cancelExecutingJobLocked(
+ running.getStopReason(),
+ JobParameters.INTERNAL_STOP_REASON_RESTRICTED_BUCKET,
+ "cancelled due to restricted bucket");
+ } else {
+ serviceContext.cancelExecutingJobLocked(
+ running.getStopReason(),
+ JobParameters.INTERNAL_STOP_REASON_CONSTRAINTS_NOT_SATISFIED,
+ "cancelled due to unsatisfied constraints");
+ }
+ } else {
+ final JobRestriction restriction = mService.checkIfRestricted(running);
+ if (restriction != null) {
+ final int internalReasonCode = restriction.getInternalReason();
+ serviceContext.cancelExecutingJobLocked(restriction.getReason(),
+ internalReasonCode,
+ "restricted due to "
+ + JobParameters.getInternalReasonCodeDescription(
+ internalReasonCode));
+ }
+ }
+ }
+ }
+
private void noteConcurrency() {
mService.mJobPackageTracker.noteConcurrency(mRunningJobs.size(),
// TODO: log per type instead of only TOP
@@ -1078,6 +1181,24 @@
}
@GuardedBy("mLock")
+ boolean executeTimeoutCommandLocked(PrintWriter pw, String pkgName, int userId,
+ boolean hasJobId, int jobId) {
+ boolean foundSome = false;
+ for (int i = 0; i < mActiveServices.size(); i++) {
+ final JobServiceContext jc = mActiveServices.get(i);
+ final JobStatus js = jc.getRunningJobLocked();
+ if (jc.timeoutIfExecutingLocked(pkgName, userId, hasJobId, jobId, "shell")) {
+ foundSome = true;
+ pw.print("Timing out: ");
+ js.printUniqueId(pw);
+ pw.print(" ");
+ pw.println(js.getServiceComponent().flattenToShortString());
+ }
+ }
+ return foundSome;
+ }
+
+ @GuardedBy("mLock")
private String printPendingQueueLocked() {
StringBuilder s = new StringBuilder("Pending queue: ");
Iterator<JobStatus> it = mService.mPendingJobs.iterator();
@@ -1200,6 +1321,43 @@
}
}
+ @GuardedBy("mLock")
+ void dumpActiveJobsLocked(IndentingPrintWriter pw, Predicate<JobStatus> predicate,
+ long nowElapsed, long nowUptime) {
+ pw.println("Active jobs:");
+ pw.increaseIndent();
+ for (int i = 0; i < mActiveServices.size(); i++) {
+ JobServiceContext jsc = mActiveServices.get(i);
+ final JobStatus job = jsc.getRunningJobLocked();
+
+ if (job != null && !predicate.test(job)) {
+ continue;
+ }
+
+ pw.print("Slot #"); pw.print(i); pw.print(": ");
+ jsc.dumpLocked(pw, nowElapsed);
+
+ if (job != null) {
+ pw.increaseIndent();
+
+ pw.increaseIndent();
+ job.dump(pw, false, nowElapsed);
+ pw.decreaseIndent();
+
+ pw.print("Evaluated bias: ");
+ pw.println(JobInfo.getBiasString(job.lastEvaluatedBias));
+
+ pw.print("Active at ");
+ TimeUtils.formatDuration(job.madeActive - nowUptime, pw);
+ pw.print(", pending for ");
+ TimeUtils.formatDuration(job.madeActive - job.madePending, pw);
+ pw.decreaseIndent();
+ pw.println();
+ }
+ }
+ pw.decreaseIndent();
+ }
+
public void dumpProtoLocked(ProtoOutputStream proto, long tag, long now, long nowRealtime) {
final long token = proto.start(tag);
diff --git a/apex/jobscheduler/service/java/com/android/server/job/JobSchedulerService.java b/apex/jobscheduler/service/java/com/android/server/job/JobSchedulerService.java
index b936278..3d74bc9 100644
--- a/apex/jobscheduler/service/java/com/android/server/job/JobSchedulerService.java
+++ b/apex/jobscheduler/service/java/com/android/server/job/JobSchedulerService.java
@@ -57,7 +57,6 @@
import android.net.Uri;
import android.os.BatteryManager;
import android.os.BatteryManagerInternal;
-import android.os.BatteryStats;
import android.os.BatteryStatsInternal;
import android.os.Binder;
import android.os.Handler;
@@ -67,7 +66,6 @@
import android.os.ParcelFileDescriptor;
import android.os.Process;
import android.os.RemoteException;
-import android.os.ServiceManager;
import android.os.SystemClock;
import android.os.UserHandle;
import android.os.WorkSource;
@@ -90,7 +88,6 @@
import com.android.internal.annotations.GuardedBy;
import com.android.internal.annotations.VisibleForTesting;
-import com.android.internal.app.IBatteryStats;
import com.android.internal.os.SomeArgs;
import com.android.internal.util.ArrayUtils;
import com.android.internal.util.DumpUtils;
@@ -100,7 +97,6 @@
import com.android.server.DeviceIdleInternal;
import com.android.server.JobSchedulerBackgroundThread;
import com.android.server.LocalServices;
-import com.android.server.job.JobSchedulerServiceDumpProto.ActiveJob;
import com.android.server.job.JobSchedulerServiceDumpProto.PendingJob;
import com.android.server.job.controllers.BackgroundJobsController;
import com.android.server.job.controllers.BatteryController;
@@ -243,12 +239,6 @@
static final int MSG_CHECK_CHANGED_JOB_LIST = 8;
static final int MSG_CHECK_MEDIA_EXEMPTION = 9;
- /**
- * Track Services that have currently active or pending jobs. The index is provided by
- * {@link JobStatus#getServiceToken()}
- */
- final List<JobServiceContext> mActiveServices = new ArrayList<>();
-
/** List of controllers that will notify this service of updates to jobs. */
final List<StateController> mControllers;
/**
@@ -307,7 +297,6 @@
PackageManagerInternal mLocalPM;
ActivityManagerInternal mActivityManagerInternal;
- IBatteryStats mBatteryStats;
DeviceIdleInternal mLocalDeviceIdleController;
@VisibleForTesting
AppStateTrackerImpl mAppStateTracker;
@@ -1578,7 +1567,8 @@
mJobPackageTracker.noteNonpending(cancelled);
}
// Cancel if running.
- stopJobOnServiceContextLocked(cancelled, reason, internalReasonCode, debugReason);
+ mConcurrencyManager.stopJobOnServiceContextLocked(
+ cancelled, reason, internalReasonCode, debugReason);
// If this is a replacement, bring in the new version of the job
if (incomingJob != null) {
if (DEBUG) Slog.i(TAG, "Tracking replacement job " + incomingJob.toShortString());
@@ -1627,19 +1617,7 @@
if (DEBUG) {
Slog.d(TAG, "Doze state changed: " + deviceIdle);
}
- if (deviceIdle) {
- // When becoming idle, make sure no jobs are actively running,
- // except those using the idle exemption flag.
- for (int i=0; i<mActiveServices.size(); i++) {
- JobServiceContext jsc = mActiveServices.get(i);
- final JobStatus executing = jsc.getRunningJobLocked();
- if (executing != null && !executing.canRunInDoze()) {
- jsc.cancelExecutingJobLocked(JobParameters.STOP_REASON_DEVICE_STATE,
- JobParameters.INTERNAL_STOP_REASON_DEVICE_IDLE,
- "cancelled due to doze");
- }
- }
- } else {
+ if (!deviceIdle) {
// When coming out of idle, allow thing to start back up.
if (mReadyToRock) {
if (mLocalDeviceIdleController != null) {
@@ -1682,10 +1660,10 @@
// active is true if pending queue contains jobs OR some job is running.
boolean active = mPendingJobs.size() > 0;
if (mPendingJobs.size() <= 0) {
- for (int i=0; i<mActiveServices.size(); i++) {
- final JobServiceContext jsc = mActiveServices.get(i);
- final JobStatus job = jsc.getRunningJobLocked();
- if (job != null && !job.canRunInDoze()) {
+ final ArraySet<JobStatus> runningJobs = mConcurrencyManager.getRunningJobsLocked();
+ for (int i = runningJobs.size() - 1; i >= 0; --i) {
+ final JobStatus job = runningJobs.valueAt(i);
+ if (!job.canRunInDoze()) {
// We will report active if we have a job running and it does not have an
// exception that allows it to run in Doze.
active = true;
@@ -1895,16 +1873,9 @@
synchronized (mLock) {
// Let's go!
mReadyToRock = true;
- mBatteryStats = IBatteryStats.Stub.asInterface(ServiceManager.getService(
- BatteryStats.SERVICE_NAME));
mLocalDeviceIdleController =
LocalServices.getService(DeviceIdleInternal.class);
- // Create the "runners".
- for (int i = 0; i < MAX_JOB_CONTEXTS_COUNT; i++) {
- mActiveServices.add(
- new JobServiceContext(this, mConcurrencyManager, mBatteryStats,
- mJobPackageTracker, getContext().getMainLooper()));
- }
+ mConcurrencyManager.onThirdPartyAppsCanStart();
// Attach jobs to their controllers.
mJobs.forEachJob((job) -> {
for (int controller = 0; controller < mControllers.size(); controller++) {
@@ -1961,19 +1932,6 @@
return removed;
}
- private boolean stopJobOnServiceContextLocked(JobStatus job,
- @JobParameters.StopReason int reason, int internalReasonCode, String debugReason) {
- for (int i = 0; i < mActiveServices.size(); i++) {
- JobServiceContext jsc = mActiveServices.get(i);
- final JobStatus executing = jsc.getRunningJobLocked();
- if (executing != null && executing.matches(job.getUid(), job.getJobId())) {
- jsc.cancelExecutingJobLocked(reason, internalReasonCode, debugReason);
- return true;
- }
- }
- return false;
- }
-
/** Return {@code true} if the specified job is currently executing. */
@GuardedBy("mLock")
public boolean isCurrentlyRunningLocked(JobStatus job) {
@@ -2383,7 +2341,8 @@
* - if passes all the restrictions or has {@link JobInfo#BIAS_FOREGROUND_SERVICE} bias
* or higher.
*/
- private JobRestriction checkIfRestricted(JobStatus job) {
+ @GuardedBy("mLock")
+ JobRestriction checkIfRestricted(JobStatus job) {
if (evaluateJobBiasLocked(job) >= JobInfo.BIAS_FOREGROUND_SERVICE) {
// Jobs with BIAS_FOREGROUND_SERVICE or higher should not be restricted
return null;
@@ -2397,38 +2356,9 @@
return null;
}
+ @GuardedBy("mLock")
private void stopNonReadyActiveJobsLocked() {
- for (int i=0; i<mActiveServices.size(); i++) {
- JobServiceContext serviceContext = mActiveServices.get(i);
- final JobStatus running = serviceContext.getRunningJobLocked();
- if (running == null) {
- continue;
- }
- if (!running.isReady()) {
- if (running.getEffectiveStandbyBucket() == RESTRICTED_INDEX
- && running.getStopReason() == JobParameters.STOP_REASON_APP_STANDBY) {
- serviceContext.cancelExecutingJobLocked(
- running.getStopReason(),
- JobParameters.INTERNAL_STOP_REASON_RESTRICTED_BUCKET,
- "cancelled due to restricted bucket");
- } else {
- serviceContext.cancelExecutingJobLocked(
- running.getStopReason(),
- JobParameters.INTERNAL_STOP_REASON_CONSTRAINTS_NOT_SATISFIED,
- "cancelled due to unsatisfied constraints");
- }
- } else {
- final JobRestriction restriction = checkIfRestricted(running);
- if (restriction != null) {
- final int internalReasonCode = restriction.getInternalReason();
- serviceContext.cancelExecutingJobLocked(restriction.getReason(),
- internalReasonCode,
- "restricted due to "
- + JobParameters.getInternalReasonCodeDescription(
- internalReasonCode));
- }
- }
- }
+ mConcurrencyManager.stopNonReadyActiveJobsLocked();
}
/**
@@ -2598,7 +2528,7 @@
debugReason = "couldn't figure out why the job should stop running";
}
}
- stopJobOnServiceContextLocked(job, job.getStopReason(),
+ mConcurrencyManager.stopJobOnServiceContextLocked(job, job.getStopReason(),
internalStopReason, debugReason);
} else if (mPendingJobs.remove(job)) {
noteJobNonPending(job);
@@ -3516,9 +3446,11 @@
final ArrayList<JobInfo> runningJobs;
synchronized (mLock) {
- runningJobs = new ArrayList<>(mActiveServices.size());
- for (JobServiceContext jsc : mActiveServices) {
- final JobStatus job = jsc.getRunningJobLocked();
+ final ArraySet<JobStatus> runningJobStatuses =
+ mConcurrencyManager.getRunningJobsLocked();
+ runningJobs = new ArrayList<>(runningJobStatuses.size());
+ for (int i = runningJobStatuses.size() - 1; i >= 0; --i) {
+ final JobStatus job = runningJobStatuses.valueAt(i);
if (job != null) {
runningJobs.add(job.getJob());
}
@@ -3599,18 +3531,8 @@
}
synchronized (mLock) {
- boolean foundSome = false;
- for (int i = 0; i < mActiveServices.size(); i++) {
- final JobServiceContext jc = mActiveServices.get(i);
- final JobStatus js = jc.getRunningJobLocked();
- if (jc.timeoutIfExecutingLocked(pkgName, userId, hasJobId, jobId, "shell")) {
- foundSome = true;
- pw.print("Timing out: ");
- js.printUniqueId(pw);
- pw.print(" ");
- pw.println(js.getServiceComponent().flattenToShortString());
- }
- }
+ final boolean foundSome = mConcurrencyManager.executeTimeoutCommandLocked(pw,
+ pkgName, userId, hasJobId, jobId);
if (!foundSome) {
pw.println("No matching executing jobs found.");
}
@@ -4037,38 +3959,7 @@
pw.decreaseIndent();
pw.println();
- pw.println("Active jobs:");
- pw.increaseIndent();
- for (int i=0; i<mActiveServices.size(); i++) {
- JobServiceContext jsc = mActiveServices.get(i);
- final JobStatus job = jsc.getRunningJobLocked();
-
- if (job != null && !predicate.test(job)) {
- continue;
- }
-
- pw.print("Slot #"); pw.print(i); pw.print(": ");
- jsc.dumpLocked(pw, nowElapsed);
-
- if (job != null) {
- pw.increaseIndent();
-
- pw.increaseIndent();
- job.dump(pw, false, nowElapsed);
- pw.decreaseIndent();
-
- pw.print("Evaluated bias: ");
- pw.println(JobInfo.getBiasString(job.lastEvaluatedBias));
-
- pw.print("Active at ");
- TimeUtils.formatDuration(job.madeActive - nowUptime, pw);
- pw.print(", pending for ");
- TimeUtils.formatDuration(job.madeActive - job.madePending, pw);
- pw.decreaseIndent();
- pw.println();
- }
- }
- pw.decreaseIndent();
+ mConcurrencyManager.dumpActiveJobsLocked(pw, predicate, nowElapsed, nowUptime);
pw.println();
boolean recentPrinted = false;
@@ -4228,45 +4119,6 @@
proto.end(pjToken);
}
- for (JobServiceContext jsc : mActiveServices) {
- final long ajToken = proto.start(JobSchedulerServiceDumpProto.ACTIVE_JOBS);
- final JobStatus job = jsc.getRunningJobLocked();
-
- if (job == null) {
- final long ijToken = proto.start(ActiveJob.INACTIVE);
-
- proto.write(ActiveJob.InactiveJob.TIME_SINCE_STOPPED_MS,
- nowElapsed - jsc.mStoppedTime);
- if (jsc.mStoppedReason != null) {
- proto.write(ActiveJob.InactiveJob.STOPPED_REASON,
- jsc.mStoppedReason);
- }
-
- proto.end(ijToken);
- } else {
- final long rjToken = proto.start(ActiveJob.RUNNING);
-
- job.writeToShortProto(proto, ActiveJob.RunningJob.INFO);
-
- proto.write(ActiveJob.RunningJob.RUNNING_DURATION_MS,
- nowElapsed - jsc.getExecutionStartTimeElapsed());
- proto.write(ActiveJob.RunningJob.TIME_UNTIL_TIMEOUT_MS,
- jsc.getTimeoutElapsed() - nowElapsed);
-
- job.dump(proto, ActiveJob.RunningJob.DUMP, false, nowElapsed);
-
- proto.write(ActiveJob.RunningJob.EVALUATED_PRIORITY,
- evaluateJobBiasLocked(job));
-
- proto.write(ActiveJob.RunningJob.TIME_SINCE_MADE_ACTIVE_MS,
- nowUptime - job.madeActive);
- proto.write(ActiveJob.RunningJob.PENDING_DURATION_MS,
- job.madeActive - job.madePending);
-
- proto.end(rjToken);
- }
- proto.end(ajToken);
- }
if (filterUid == -1) {
proto.write(JobSchedulerServiceDumpProto.IS_READY_TO_ROCK, mReadyToRock);
proto.write(JobSchedulerServiceDumpProto.REPORTED_ACTIVE, mReportedActive);
diff --git a/apex/jobscheduler/service/java/com/android/server/job/controllers/JobStatus.java b/apex/jobscheduler/service/java/com/android/server/job/controllers/JobStatus.java
index efcf14f..30fdb1e 100644
--- a/apex/jobscheduler/service/java/com/android/server/job/controllers/JobStatus.java
+++ b/apex/jobscheduler/service/java/com/android/server/job/controllers/JobStatus.java
@@ -441,11 +441,6 @@
/** The reason a job most recently went from ready to not ready. */
private int mReasonReadyToUnready = JobParameters.STOP_REASON_UNDEFINED;
- /** Provide a handle to the service that this job will be run on. */
- public int getServiceToken() {
- return callingUid;
- }
-
/**
* Core constructor for JobStatus instances. All other ctors funnel down to this one.
*
diff --git a/apex/jobscheduler/service/java/com/android/server/tare/ProcessStateModifier.java b/apex/jobscheduler/service/java/com/android/server/tare/ProcessStateModifier.java
index 67a3dc6..5ec2f56 100644
--- a/apex/jobscheduler/service/java/com/android/server/tare/ProcessStateModifier.java
+++ b/apex/jobscheduler/service/java/com/android/server/tare/ProcessStateModifier.java
@@ -146,8 +146,11 @@
return 0;
case PROC_STATE_BUCKET_FGS:
// Can't get notification priority. Just use CTP for now.
- return ctp;
+ return Math.min(ctp, price);
case PROC_STATE_BUCKET_BFGS:
+ if (price <= ctp) {
+ return price;
+ }
return (long) (ctp + .5 * (price - ctp));
case PROC_STATE_BUCKET_BG:
default:
diff --git a/apex/jobscheduler/service/java/com/android/server/usage/AppIdleHistory.java b/apex/jobscheduler/service/java/com/android/server/usage/AppIdleHistory.java
index dd102bd..2e3b377 100644
--- a/apex/jobscheduler/service/java/com/android/server/usage/AppIdleHistory.java
+++ b/apex/jobscheduler/service/java/com/android/server/usage/AppIdleHistory.java
@@ -384,14 +384,16 @@
return userHistory;
}
+ // TODO (206518483): Remove unused parameter 'elapsedRealtime'.
private AppUsageHistory getPackageHistory(ArrayMap<String, AppUsageHistory> userHistory,
String packageName, long elapsedRealtime, boolean create) {
AppUsageHistory appUsageHistory = userHistory.get(packageName);
if (appUsageHistory == null && create) {
appUsageHistory = new AppUsageHistory();
- appUsageHistory.lastUsedElapsedTime = getElapsedTime(elapsedRealtime);
- appUsageHistory.lastUsedScreenTime = getScreenOnTime(elapsedRealtime);
- appUsageHistory.lastPredictedTime = getElapsedTime(0);
+ appUsageHistory.lastUsedByUserElapsedTime = Integer.MIN_VALUE;
+ appUsageHistory.lastUsedElapsedTime = Integer.MIN_VALUE;
+ appUsageHistory.lastUsedScreenTime = Integer.MIN_VALUE;
+ appUsageHistory.lastPredictedTime = Integer.MIN_VALUE;
appUsageHistory.currentBucket = STANDBY_BUCKET_NEVER;
appUsageHistory.bucketingReason = REASON_MAIN_DEFAULT;
appUsageHistory.lastInformedBucket = -1;
@@ -544,7 +546,7 @@
AppUsageHistory appUsageHistory =
getPackageHistory(userHistory, packageName, elapsedRealtime, false);
if (appUsageHistory == null || appUsageHistory.lastUsedByUserElapsedTime == Long.MIN_VALUE
- || appUsageHistory.lastUsedByUserElapsedTime == 0) {
+ || appUsageHistory.lastUsedByUserElapsedTime <= 0) {
return Long.MAX_VALUE;
}
return getElapsedTime(elapsedRealtime) - appUsageHistory.lastUsedByUserElapsedTime;
@@ -631,8 +633,12 @@
// If we don't have any state for the app, assume never used
if (appUsageHistory == null) return screenTimeThresholds.length - 1;
- long screenOnDelta = getScreenOnTime(elapsedRealtime) - appUsageHistory.lastUsedScreenTime;
- long elapsedDelta = getElapsedTime(elapsedRealtime) - appUsageHistory.lastUsedElapsedTime;
+ long screenOnDelta = appUsageHistory.lastUsedScreenTime >= 0
+ ? getScreenOnTime(elapsedRealtime) - appUsageHistory.lastUsedScreenTime
+ : Long.MAX_VALUE;
+ long elapsedDelta = appUsageHistory.lastUsedElapsedTime >= 0
+ ? getElapsedTime(elapsedRealtime) - appUsageHistory.lastUsedElapsedTime
+ : Long.MAX_VALUE;
if (DEBUG) Slog.d(TAG, packageName
+ " lastUsedScreen=" + appUsageHistory.lastUsedScreenTime
@@ -667,8 +673,8 @@
long getBucketExpiryTimeMs(String packageName, int userId, int bucket, long elapsedRealtimeMs) {
ArrayMap<String, AppUsageHistory> userHistory = getUserHistory(userId);
AppUsageHistory appUsageHistory = getPackageHistory(userHistory, packageName,
- elapsedRealtimeMs, true);
- if (appUsageHistory.bucketExpiryTimesMs == null) {
+ elapsedRealtimeMs, false /* create */);
+ if (appUsageHistory == null || appUsageHistory.bucketExpiryTimesMs == null) {
return 0;
}
return appUsageHistory.bucketExpiryTimesMs.get(bucket, 0);
@@ -951,14 +957,14 @@
+ " reason="
+ UsageStatsManager.reasonToString(appUsageHistory.bucketingReason));
idpw.print(" used=");
- TimeUtils.formatDuration(totalElapsedTime - appUsageHistory.lastUsedElapsedTime, idpw);
+ printLastActionElapsedTime(idpw, totalElapsedTime, appUsageHistory.lastUsedElapsedTime);
idpw.print(" usedByUser=");
- TimeUtils.formatDuration(totalElapsedTime - appUsageHistory.lastUsedByUserElapsedTime,
- idpw);
+ printLastActionElapsedTime(idpw, totalElapsedTime,
+ appUsageHistory.lastUsedByUserElapsedTime);
idpw.print(" usedScr=");
- TimeUtils.formatDuration(screenOnTime - appUsageHistory.lastUsedScreenTime, idpw);
+ printLastActionElapsedTime(idpw, totalElapsedTime, appUsageHistory.lastUsedScreenTime);
idpw.print(" lastPred=");
- TimeUtils.formatDuration(totalElapsedTime - appUsageHistory.lastPredictedTime, idpw);
+ printLastActionElapsedTime(idpw, totalElapsedTime, appUsageHistory.lastPredictedTime);
dumpBucketExpiryTimes(idpw, appUsageHistory, totalElapsedTime);
idpw.print(" lastJob=");
TimeUtils.formatDuration(totalElapsedTime - appUsageHistory.lastJobRunTime, idpw);
@@ -986,6 +992,15 @@
idpw.decreaseIndent();
}
+ private void printLastActionElapsedTime(IndentingPrintWriter idpw, long totalElapsedTimeMS,
+ long lastActionTimeMs) {
+ if (lastActionTimeMs < 0) {
+ idpw.print("<uninitialized>");
+ } else {
+ TimeUtils.formatDuration(totalElapsedTimeMS - lastActionTimeMs, idpw);
+ }
+ }
+
private void dumpBucketExpiryTimes(IndentingPrintWriter idpw, AppUsageHistory appUsageHistory,
long totalElapsedTimeMs) {
idpw.print(" expiryTimes=");
diff --git a/apex/jobscheduler/service/java/com/android/server/usage/AppStandbyController.java b/apex/jobscheduler/service/java/com/android/server/usage/AppStandbyController.java
index 4952894..5029130 100644
--- a/apex/jobscheduler/service/java/com/android/server/usage/AppStandbyController.java
+++ b/apex/jobscheduler/service/java/com/android/server/usage/AppStandbyController.java
@@ -100,6 +100,7 @@
import android.provider.DeviceConfig;
import android.provider.Settings.Global;
import android.telephony.TelephonyManager;
+import android.util.ArrayMap;
import android.util.ArraySet;
import android.util.IndentingPrintWriter;
import android.util.Slog;
@@ -130,6 +131,7 @@
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
+import java.util.Map;
import java.util.Set;
import java.util.concurrent.CountDownLatch;
@@ -375,6 +377,15 @@
ConstantsObserver.DEFAULT_BROADCAST_RESPONSE_FG_THRESHOLD_STATE;
/**
+ * Map of last known values of keys in {@link DeviceConfig#NAMESPACE_APP_STANDBY}.
+ *
+ * Note: We are intentionally not guarding this by any lock since this is only updated on
+ * a handler thread and when querying, if we do end up seeing slightly older values, it is fine
+ * since the values are only used in tests and doesn't need to be queried in any other cases.
+ */
+ private final Map<String, String> mAppStandbyProperties = new ArrayMap<>();
+
+ /**
* Whether we should allow apps into the
* {@link android.app.usage.UsageStatsManager#STANDBY_BUCKET_RESTRICTED} bucket or not.
* If false, any attempts to put an app into the bucket will put the app into the
@@ -887,8 +898,11 @@
}
}
+ final long elapsedLastUsedByUserTimeDelta = app.lastUsedByUserElapsedTime >= 0
+ ? elapsedTimeAdjusted - app.lastUsedByUserElapsedTime
+ : Long.MAX_VALUE;
if (app.lastRestrictAttemptElapsedTime > app.lastUsedByUserElapsedTime
- && elapsedTimeAdjusted - app.lastUsedByUserElapsedTime
+ && elapsedLastUsedByUserTimeDelta
>= mInjector.getAutoRestrictedBucketDelayMs()) {
newBucket = STANDBY_BUCKET_RESTRICTED;
reason = app.lastRestrictReason;
@@ -1837,6 +1851,12 @@
}
@Override
+ @Nullable
+ public String getAppStandbyConstant(@NonNull String key) {
+ return mAppStandbyProperties.get(key);
+ }
+
+ @Override
public void flushToDisk() {
synchronized (mAppIdleLock) {
mAppIdleHistory.writeAppIdleTimes(mInjector.elapsedRealtime());
@@ -2774,6 +2794,7 @@
}
break;
}
+ mAppStandbyProperties.put(name, properties.getString(name, null));
}
}
}
diff --git a/cmds/am/src/com/android/commands/am/Am.java b/cmds/am/src/com/android/commands/am/Am.java
index c5410a0..b8d24e3 100644
--- a/cmds/am/src/com/android/commands/am/Am.java
+++ b/cmds/am/src/com/android/commands/am/Am.java
@@ -191,6 +191,8 @@
instrument.noRestart = true;
} else if (opt.equals("--always-check-signature")) {
instrument.alwaysCheckSignature = true;
+ } else if (opt.equals("--instrument-sdk-sandbox")) {
+ instrument.instrumentSdkSandbox = true;
} else {
System.err.println("Error: Unknown option: " + opt);
return;
diff --git a/cmds/am/src/com/android/commands/am/Instrument.java b/cmds/am/src/com/android/commands/am/Instrument.java
index a0562d9..7ff4bc4 100644
--- a/cmds/am/src/com/android/commands/am/Instrument.java
+++ b/cmds/am/src/com/android/commands/am/Instrument.java
@@ -20,6 +20,7 @@
import static android.app.ActivityManager.INSTR_FLAG_DISABLE_HIDDEN_API_CHECKS;
import static android.app.ActivityManager.INSTR_FLAG_DISABLE_ISOLATED_STORAGE;
import static android.app.ActivityManager.INSTR_FLAG_DISABLE_TEST_API_CHECKS;
+import static android.app.ActivityManager.INSTR_FLAG_INSTRUMENT_SDK_SANDBOX;
import static android.app.ActivityManager.INSTR_FLAG_NO_RESTART;
import android.app.IActivityManager;
@@ -97,6 +98,7 @@
// Required
public String componentNameArg;
public boolean alwaysCheckSignature = false;
+ public boolean instrumentSdkSandbox = false;
/**
* Construct the instrument command runner.
@@ -524,6 +526,9 @@
if (alwaysCheckSignature) {
flags |= INSTR_FLAG_ALWAYS_CHECK_SIGNATURE;
}
+ if (instrumentSdkSandbox) {
+ flags |= INSTR_FLAG_INSTRUMENT_SDK_SANDBOX;
+ }
if (!mAm.startInstrumentation(cn, profileFile, flags, args, watcher, connection, userId,
abi)) {
throw new AndroidException("INSTRUMENTATION_FAILED: " + cn.flattenToString());
diff --git a/cmds/app_process/Android.bp b/cmds/app_process/Android.bp
index 6a685a7..a157517 100644
--- a/cmds/app_process/Android.bp
+++ b/cmds/app_process/Android.bp
@@ -64,8 +64,6 @@
"libwilhelm",
],
- header_libs: ["bionic_libc_platform_headers"],
-
compile_multilib: "both",
cflags: [
diff --git a/cmds/app_process/app_main.cpp b/cmds/app_process/app_main.cpp
index 815f945..12083b6 100644
--- a/cmds/app_process/app_main.cpp
+++ b/cmds/app_process/app_main.cpp
@@ -15,7 +15,6 @@
#include <android-base/macros.h>
#include <binder/IPCThreadState.h>
-#include <bionic/pac.h>
#include <hwbinder/IPCThreadState.h>
#include <utils/Log.h>
#include <cutils/memory.h>
@@ -183,10 +182,6 @@
ALOGV("app_process main with argv: %s", argv_String.string());
}
- // Because of applications that are using PAC instructions incorrectly, PAC
- // is disabled in application processes for now.
- ScopedDisablePAC x;
-
AppRuntime runtime(argv[0], computeArgBlockSize(argc, argv));
// Process command line arguments
// ignore argv[0]
diff --git a/cmds/idmap2/Android.bp b/cmds/idmap2/Android.bp
index c202f6f..6ef6845 100644
--- a/cmds/idmap2/Android.bp
+++ b/cmds/idmap2/Android.bp
@@ -52,6 +52,7 @@
"-readability-braces-around-statements",
"-readability-const-return-type",
"-readability-convert-member-functions-to-static",
+ "-readability-duplicate-include",
"-readability-else-after-return",
"-readability-identifier-length",
"-readability-named-parameter",
diff --git a/core/api/current.txt b/core/api/current.txt
index 19ffd36..786c07b 100644
--- a/core/api/current.txt
+++ b/core/api/current.txt
@@ -854,7 +854,6 @@
field public static final int indicatorRight = 16843022; // 0x101010e
field public static final int indicatorStart = 16843729; // 0x10103d1
field public static final int inflatedId = 16842995; // 0x10100f3
- field public static final int inheritKeyStoreKeys;
field public static final int inheritShowWhenLocked = 16844188; // 0x101059c
field public static final int initOrder = 16842778; // 0x101001a
field public static final int initialKeyguardLayout = 16843714; // 0x10103c2
@@ -3901,7 +3900,7 @@
method public Object getAnimatedValue(String);
method public long getCurrentPlayTime();
method public long getDuration();
- method @FloatRange(from=0, to=1) public static float getDurationScale();
+ method @FloatRange(from=0) public static float getDurationScale();
method public static long getFrameDelay();
method public int getRepeatCount();
method public int getRepeatMode();
@@ -3941,7 +3940,7 @@
}
public static interface ValueAnimator.DurationScaleChangeListener {
- method public void onChanged(float);
+ method public void onChanged(@FloatRange(from=0) float);
}
}
@@ -4532,22 +4531,36 @@
}
public static class ActivityManager.TaskDescription implements android.os.Parcelable {
- ctor public ActivityManager.TaskDescription(String, @DrawableRes int, int);
- ctor public ActivityManager.TaskDescription(String, @DrawableRes int);
- ctor public ActivityManager.TaskDescription(String);
- ctor public ActivityManager.TaskDescription();
+ ctor @Deprecated public ActivityManager.TaskDescription(String, @DrawableRes int, int);
+ ctor @Deprecated public ActivityManager.TaskDescription(String, @DrawableRes int);
+ ctor @Deprecated public ActivityManager.TaskDescription(String);
+ ctor @Deprecated public ActivityManager.TaskDescription();
ctor @Deprecated public ActivityManager.TaskDescription(String, android.graphics.Bitmap, int);
ctor @Deprecated public ActivityManager.TaskDescription(String, android.graphics.Bitmap);
ctor public ActivityManager.TaskDescription(android.app.ActivityManager.TaskDescription);
method public int describeContents();
+ method @ColorInt public int getBackgroundColor();
method @Deprecated public android.graphics.Bitmap getIcon();
method public String getLabel();
- method public int getPrimaryColor();
+ method @ColorInt public int getNavigationBarColor();
+ method @ColorInt public int getPrimaryColor();
+ method @ColorInt public int getStatusBarColor();
method public void readFromParcel(android.os.Parcel);
method public void writeToParcel(android.os.Parcel, int);
field @NonNull public static final android.os.Parcelable.Creator<android.app.ActivityManager.TaskDescription> CREATOR;
}
+ public static final class ActivityManager.TaskDescription.Builder {
+ ctor public ActivityManager.TaskDescription.Builder();
+ method @NonNull public android.app.ActivityManager.TaskDescription build();
+ method @NonNull public android.app.ActivityManager.TaskDescription.Builder setBackgroundColor(@ColorInt int);
+ method @NonNull public android.app.ActivityManager.TaskDescription.Builder setIcon(@DrawableRes int);
+ method @NonNull public android.app.ActivityManager.TaskDescription.Builder setLabel(@Nullable String);
+ method @NonNull public android.app.ActivityManager.TaskDescription.Builder setNavigationBarColor(@ColorInt int);
+ method @NonNull public android.app.ActivityManager.TaskDescription.Builder setPrimaryColor(@ColorInt int);
+ method @NonNull public android.app.ActivityManager.TaskDescription.Builder setStatusBarColor(@ColorInt int);
+ }
+
public class ActivityOptions {
method @Nullable public android.graphics.Rect getLaunchBounds();
method public int getLaunchDisplayId();
@@ -5630,6 +5643,7 @@
method public boolean onException(Object, Throwable);
method public void onStart();
method public void removeMonitor(android.app.Instrumentation.ActivityMonitor);
+ method public void resetInTouchMode();
method public void runOnMainSync(Runnable);
method public void sendCharacterSync(int);
method public void sendKeyDownUpSync(int);
@@ -5814,6 +5828,7 @@
public class LocaleManager {
method @NonNull public android.os.LocaleList getApplicationLocales();
method @NonNull @RequiresPermission(value="android.permission.READ_APP_SPECIFIC_LOCALES", conditional=true) public android.os.LocaleList getApplicationLocales(@NonNull String);
+ method @NonNull public android.os.LocaleList getSystemLocales();
method public void setApplicationLocales(@NonNull android.os.LocaleList);
}
@@ -6644,6 +6659,15 @@
public final class PictureInPictureParams implements android.os.Parcelable {
method public int describeContents();
+ method @NonNull public java.util.List<android.app.RemoteAction> getActions();
+ method @Nullable public android.util.Rational getAspectRatio();
+ method @Nullable public android.app.RemoteAction getCloseAction();
+ method @Nullable public android.util.Rational getExpandedAspectRatio();
+ method @Nullable public android.graphics.Rect getSourceRectHint();
+ method @Nullable public CharSequence getSubtitle();
+ method @Nullable public CharSequence getTitle();
+ method public boolean isAutoEnterEnabled();
+ method public boolean isSeamlessResizeEnabled();
method public void writeToParcel(android.os.Parcel, int);
field @NonNull public static final android.os.Parcelable.Creator<android.app.PictureInPictureParams> CREATOR;
}
@@ -7397,12 +7421,6 @@
method @NonNull public java.util.List<java.lang.String> getDelegatedScopes(@Nullable android.content.ComponentName, @NonNull String);
method public CharSequence getDeviceOwnerLockScreenInfo();
method @Nullable public String getDevicePolicyManagementRoleHolderPackage();
- method @Nullable public android.graphics.drawable.Drawable getDrawable(@NonNull String, @NonNull String, @NonNull java.util.function.Supplier<android.graphics.drawable.Drawable>);
- method @Nullable public android.graphics.drawable.Drawable getDrawable(@NonNull String, @NonNull String, @NonNull String, @NonNull java.util.function.Supplier<android.graphics.drawable.Drawable>);
- method @Nullable public android.graphics.drawable.Icon getDrawableAsIcon(@NonNull String, @NonNull String, @NonNull String, @Nullable android.graphics.drawable.Icon);
- method @Nullable public android.graphics.drawable.Icon getDrawableAsIcon(@NonNull String, @NonNull String, @Nullable android.graphics.drawable.Icon);
- method @Nullable public android.graphics.drawable.Drawable getDrawableForDensity(@NonNull String, @NonNull String, int, @NonNull java.util.function.Supplier<android.graphics.drawable.Drawable>);
- method @Nullable public android.graphics.drawable.Drawable getDrawableForDensity(@NonNull String, @NonNull String, @NonNull String, int, @NonNull java.util.function.Supplier<android.graphics.drawable.Drawable>);
method public CharSequence getEndUserSessionMessage(@NonNull android.content.ComponentName);
method @NonNull public String getEnrollmentSpecificId();
method @Nullable public android.app.admin.FactoryResetProtectionPolicy getFactoryResetProtectionPolicy(@Nullable android.content.ComponentName);
@@ -7449,6 +7467,7 @@
method @NonNull public java.util.List<android.app.admin.PreferentialNetworkServiceConfig> getPreferentialNetworkServiceConfigs();
method public int getRequiredPasswordComplexity();
method public long getRequiredStrongAuthTimeout(@Nullable android.content.ComponentName);
+ method @NonNull public android.app.admin.DevicePolicyResourcesManager getResources();
method public boolean getScreenCaptureDisabled(@Nullable android.content.ComponentName);
method public java.util.List<android.os.UserHandle> getSecondaryUsers(@NonNull android.content.ComponentName);
method public CharSequence getShortSupportMessage(@NonNull android.content.ComponentName);
@@ -7696,6 +7715,7 @@
field public static final String EXTRA_PROVISIONING_SKIP_ENCRYPTION = "android.app.extra.PROVISIONING_SKIP_ENCRYPTION";
field @Deprecated public static final String EXTRA_PROVISIONING_SKIP_USER_CONSENT = "android.app.extra.PROVISIONING_SKIP_USER_CONSENT";
field public static final String EXTRA_PROVISIONING_TIME_ZONE = "android.app.extra.PROVISIONING_TIME_ZONE";
+ field public static final String EXTRA_PROVISIONING_USE_MOBILE_DATA = "android.app.extra.PROVISIONING_USE_MOBILE_DATA";
field public static final String EXTRA_PROVISIONING_WIFI_ANONYMOUS_IDENTITY = "android.app.extra.PROVISIONING_WIFI_ANONYMOUS_IDENTITY";
field public static final String EXTRA_PROVISIONING_WIFI_CA_CERTIFICATE = "android.app.extra.PROVISIONING_WIFI_CA_CERTIFICATE";
field public static final String EXTRA_PROVISIONING_WIFI_DOMAIN = "android.app.extra.PROVISIONING_WIFI_DOMAIN";
@@ -7815,31 +7835,18 @@
}
public final class DevicePolicyResources {
- }
-
- public static final class DevicePolicyResources.Drawables {
- field public static final String UNDEFINED = "UNDEFINED";
- field public static final String WORK_PROFILE_ICON = "WORK_PROFILE_ICON";
- field public static final String WORK_PROFILE_ICON_BADGE = "WORK_PROFILE_ICON_BADGE";
- field public static final String WORK_PROFILE_OFF_ICON = "WORK_PROFILE_OFF_ICON";
- field public static final String WORK_PROFILE_USER_ICON = "WORK_PROFILE_USER_ICON";
- }
-
- public static final class DevicePolicyResources.Drawables.Source {
- field public static final String HOME_WIDGET = "HOME_WIDGET";
- field public static final String LAUNCHER_OFF_BUTTON = "LAUNCHER_OFF_BUTTON";
- field public static final String NOTIFICATION = "NOTIFICATION";
- field public static final String PROFILE_SWITCH_ANIMATION = "PROFILE_SWITCH_ANIMATION";
- field public static final String QUICK_SETTINGS = "QUICK_SETTINGS";
- field public static final String STATUS_BAR = "STATUS_BAR";
field public static final String UNDEFINED = "UNDEFINED";
}
- public static final class DevicePolicyResources.Drawables.Style {
- field public static final String DEFAULT = "DEFAULT";
- field public static final String OUTLINE = "OUTLINE";
- field public static final String SOLID_COLORED = "SOLID_COLORED";
- field public static final String SOLID_NOT_COLORED = "SOLID_NOT_COLORED";
+ public class DevicePolicyResourcesManager {
+ method @Nullable public android.graphics.drawable.Drawable getDrawable(@NonNull String, @NonNull String, @NonNull java.util.function.Supplier<android.graphics.drawable.Drawable>);
+ method @Nullable public android.graphics.drawable.Drawable getDrawable(@NonNull String, @NonNull String, @NonNull String, @NonNull java.util.function.Supplier<android.graphics.drawable.Drawable>);
+ method @Nullable public android.graphics.drawable.Icon getDrawableAsIcon(@NonNull String, @NonNull String, @NonNull String, @Nullable android.graphics.drawable.Icon);
+ method @Nullable public android.graphics.drawable.Icon getDrawableAsIcon(@NonNull String, @NonNull String, @Nullable android.graphics.drawable.Icon);
+ method @Nullable public android.graphics.drawable.Drawable getDrawableForDensity(@NonNull String, @NonNull String, int, @NonNull java.util.function.Supplier<android.graphics.drawable.Drawable>);
+ method @Nullable public android.graphics.drawable.Drawable getDrawableForDensity(@NonNull String, @NonNull String, @NonNull String, int, @NonNull java.util.function.Supplier<android.graphics.drawable.Drawable>);
+ method @Nullable public String getString(@NonNull String, @NonNull java.util.function.Supplier<java.lang.String>);
+ method @Nullable public String getString(@NonNull String, @NonNull java.util.function.Supplier<java.lang.String>, @NonNull java.lang.Object...);
}
public final class DnsEvent extends android.app.admin.NetworkEvent implements android.os.Parcelable {
@@ -9726,8 +9733,8 @@
method @Nullable public abstract android.content.Intent registerReceiver(android.content.BroadcastReceiver, android.content.IntentFilter, @Nullable String, @Nullable android.os.Handler, int);
method @Deprecated @RequiresPermission(android.Manifest.permission.BROADCAST_STICKY) public abstract void removeStickyBroadcast(@RequiresPermission android.content.Intent);
method @Deprecated @RequiresPermission(allOf={"android.permission.INTERACT_ACROSS_USERS", android.Manifest.permission.BROADCAST_STICKY}) public abstract void removeStickyBroadcastAsUser(@RequiresPermission android.content.Intent, android.os.UserHandle);
- method public void revokeOwnPermissionOnKill(@NonNull String);
- method public void revokeOwnPermissionsOnKill(@NonNull java.util.Collection<java.lang.String>);
+ method public void revokeSelfPermissionOnKill(@NonNull String);
+ method public void revokeSelfPermissionsOnKill(@NonNull java.util.Collection<java.lang.String>);
method public abstract void revokeUriPermission(android.net.Uri, int);
method public abstract void revokeUriPermission(String, android.net.Uri, int);
method public abstract void sendBroadcast(@RequiresPermission android.content.Intent);
@@ -10115,12 +10122,16 @@
method @Nullable public long[] getLongArrayExtra(String);
method public long getLongExtra(String, long);
method @Nullable public String getPackage();
- method @Nullable public android.os.Parcelable[] getParcelableArrayExtra(String);
- method @Nullable public <T extends android.os.Parcelable> java.util.ArrayList<T> getParcelableArrayListExtra(String);
- method @Nullable public <T extends android.os.Parcelable> T getParcelableExtra(String);
+ method @Deprecated @Nullable public android.os.Parcelable[] getParcelableArrayExtra(String);
+ method @Nullable public <T> T[] getParcelableArrayExtra(@Nullable String, @NonNull Class<T>);
+ method @Deprecated @Nullable public <T extends android.os.Parcelable> java.util.ArrayList<T> getParcelableArrayListExtra(String);
+ method @Nullable public <T> java.util.ArrayList<T> getParcelableArrayListExtra(@Nullable String, @NonNull Class<? extends T>);
+ method @Deprecated @Nullable public <T extends android.os.Parcelable> T getParcelableExtra(String);
+ method @Nullable public <T> T getParcelableExtra(@Nullable String, @NonNull Class<T>);
method @Nullable public String getScheme();
method @Nullable public android.content.Intent getSelector();
- method @Nullable public java.io.Serializable getSerializableExtra(String);
+ method @Deprecated @Nullable public java.io.Serializable getSerializableExtra(String);
+ method @Nullable public <T extends java.io.Serializable> T getSerializableExtra(@Nullable String, @NonNull Class<T>);
method @Nullable public short[] getShortArrayExtra(String);
method public short getShortExtra(String, short);
method @Nullable public android.graphics.Rect getSourceBounds();
@@ -10429,13 +10440,11 @@
field public static final String EXTRA_LOCAL_ONLY = "android.intent.extra.LOCAL_ONLY";
field public static final String EXTRA_LOCUS_ID = "android.intent.extra.LOCUS_ID";
field public static final String EXTRA_MIME_TYPES = "android.intent.extra.MIME_TYPES";
- field public static final String EXTRA_NEW_UID = "android.intent.extra.NEW_UID";
field public static final String EXTRA_NOT_UNKNOWN_SOURCE = "android.intent.extra.NOT_UNKNOWN_SOURCE";
field public static final String EXTRA_ORIGINATING_URI = "android.intent.extra.ORIGINATING_URI";
field public static final String EXTRA_PACKAGE_NAME = "android.intent.extra.PACKAGE_NAME";
field public static final String EXTRA_PERMISSION_GROUP_NAME = "android.intent.extra.PERMISSION_GROUP_NAME";
field public static final String EXTRA_PHONE_NUMBER = "android.intent.extra.PHONE_NUMBER";
- field public static final String EXTRA_PREVIOUS_UID = "android.intent.extra.PREVIOUS_UID";
field public static final String EXTRA_PROCESS_TEXT = "android.intent.extra.PROCESS_TEXT";
field public static final String EXTRA_PROCESS_TEXT_READONLY = "android.intent.extra.PROCESS_TEXT_READONLY";
field public static final String EXTRA_QUICK_VIEW_FEATURES = "android.intent.extra.QUICK_VIEW_FEATURES";
@@ -10467,7 +10476,6 @@
field public static final String EXTRA_TIMEZONE = "time-zone";
field public static final String EXTRA_TITLE = "android.intent.extra.TITLE";
field public static final String EXTRA_UID = "android.intent.extra.UID";
- field public static final String EXTRA_UID_CHANGING = "android.intent.extra.UID_CHANGING";
field public static final String EXTRA_USER = "android.intent.extra.USER";
field public static final String EXTRA_USER_INITIATED = "android.intent.extra.USER_INITIATED";
field public static final int FILL_IN_ACTION = 1; // 0x1
@@ -11230,6 +11238,33 @@
field @NonNull public static final android.os.Parcelable.Creator<android.content.pm.Attribution> CREATOR;
}
+ public final class Capability implements android.os.Parcelable {
+ method public int describeContents();
+ method @NonNull public String getName();
+ method public void writeToParcel(@NonNull android.os.Parcel, int);
+ field @NonNull public static final android.os.Parcelable.Creator<android.content.pm.Capability> CREATOR;
+ }
+
+ public static final class Capability.Builder {
+ ctor public Capability.Builder(@NonNull String);
+ method @NonNull public android.content.pm.Capability build();
+ }
+
+ public final class CapabilityParams implements android.os.Parcelable {
+ method public int describeContents();
+ method @NonNull public java.util.List<java.lang.String> getAliases();
+ method @NonNull public String getName();
+ method @NonNull public String getValue();
+ method public void writeToParcel(@NonNull android.os.Parcel, int);
+ field @NonNull public static final android.os.Parcelable.Creator<android.content.pm.CapabilityParams> CREATOR;
+ }
+
+ public static final class CapabilityParams.Builder {
+ ctor public CapabilityParams.Builder(@NonNull String, @NonNull String);
+ method @NonNull public android.content.pm.CapabilityParams.Builder addAlias(@NonNull String);
+ method @NonNull public android.content.pm.CapabilityParams build();
+ }
+
public final class ChangedPackages implements android.os.Parcelable {
ctor public ChangedPackages(int, @NonNull java.util.List<java.lang.String>);
method public int describeContents();
@@ -11300,6 +11335,7 @@
method @RequiresPermission(anyOf={android.Manifest.permission.INTERACT_ACROSS_PROFILES, "android.permission.INTERACT_ACROSS_USERS"}) public void startActivity(@NonNull android.content.Intent, @NonNull android.os.UserHandle, @Nullable android.app.Activity);
method @RequiresPermission(anyOf={android.Manifest.permission.INTERACT_ACROSS_PROFILES, "android.permission.INTERACT_ACROSS_USERS"}) public void startActivity(@NonNull android.content.Intent, @NonNull android.os.UserHandle, @Nullable android.app.Activity, @Nullable android.os.Bundle);
method public void startMainActivity(@NonNull android.content.ComponentName, @NonNull android.os.UserHandle);
+ method public void startMainActivity(@NonNull android.content.ComponentName, @NonNull android.os.UserHandle, @Nullable android.app.Activity, @Nullable android.os.Bundle);
field public static final String ACTION_CAN_INTERACT_ACROSS_PROFILES_CHANGED = "android.content.pm.action.CAN_INTERACT_ACROSS_PROFILES_CHANGED";
}
@@ -12290,7 +12326,8 @@
method @NonNull public static android.content.pm.ShortcutInfo createFromGenericDocument(@NonNull android.content.Context, @NonNull android.app.appsearch.GenericDocument);
method public int describeContents();
method @Nullable public android.content.ComponentName getActivity();
- method @NonNull public java.util.List<java.lang.String> getCapabilityParameterValues(@NonNull String, @NonNull String);
+ method @NonNull public java.util.List<android.content.pm.Capability> getCapabilities();
+ method @NonNull public java.util.List<android.content.pm.CapabilityParams> getCapabilityParams(@NonNull android.content.pm.Capability);
method @Nullable public java.util.Set<java.lang.String> getCategories();
method @Nullable public CharSequence getDisabledMessage();
method public int getDisabledReason();
@@ -12305,7 +12342,6 @@
method public int getRank();
method @Nullable public CharSequence getShortLabel();
method public android.os.UserHandle getUserHandle();
- method public boolean hasCapability(@NonNull String);
method public boolean hasKeyFieldsOnly();
method public boolean isCached();
method public boolean isDeclaredInManifest();
@@ -12330,7 +12366,7 @@
public static class ShortcutInfo.Builder {
ctor public ShortcutInfo.Builder(android.content.Context, String);
- method @NonNull public android.content.pm.ShortcutInfo.Builder addCapabilityBinding(@NonNull String, @Nullable String, @Nullable java.util.List<java.lang.String>);
+ method @NonNull public android.content.pm.ShortcutInfo.Builder addCapabilityBinding(@NonNull android.content.pm.Capability, @Nullable android.content.pm.CapabilityParams);
method @NonNull public android.content.pm.ShortcutInfo build();
method @NonNull public android.content.pm.ShortcutInfo.Builder setActivity(@NonNull android.content.ComponentName);
method @NonNull public android.content.pm.ShortcutInfo.Builder setCategories(java.util.Set<java.lang.String>);
@@ -16407,12 +16443,8 @@
package android.graphics.text {
public final class LineBreakConfig {
- ctor public LineBreakConfig();
method public int getLineBreakStyle();
method public int getLineBreakWordStyle();
- method public void set(@NonNull android.graphics.text.LineBreakConfig);
- method public void setLineBreakStyle(int);
- method public void setLineBreakWordStyle(int);
field public static final int LINE_BREAK_STYLE_LOOSE = 1; // 0x1
field public static final int LINE_BREAK_STYLE_NONE = 0; // 0x0
field public static final int LINE_BREAK_STYLE_NORMAL = 2; // 0x2
@@ -16421,6 +16453,13 @@
field public static final int LINE_BREAK_WORD_STYLE_PHRASE = 1; // 0x1
}
+ public static final class LineBreakConfig.Builder {
+ ctor public LineBreakConfig.Builder();
+ method @NonNull public android.graphics.text.LineBreakConfig build();
+ method @NonNull public android.graphics.text.LineBreakConfig.Builder setLineBreakStyle(int);
+ method @NonNull public android.graphics.text.LineBreakConfig.Builder setLineBreakWordStyle(int);
+ }
+
public class LineBreaker {
method @NonNull public android.graphics.text.LineBreaker.Result computeLineBreaks(@NonNull android.graphics.text.MeasuredText, @NonNull android.graphics.text.LineBreaker.ParagraphConstraints, @IntRange(from=0) int);
field public static final int BREAK_STRATEGY_BALANCED = 2; // 0x2
@@ -17408,7 +17447,7 @@
field @NonNull public static final android.hardware.camera2.CameraCharacteristics.Key<java.lang.Long> REQUEST_RECOMMENDED_TEN_BIT_DYNAMIC_RANGE_PROFILE;
field @NonNull public static final android.hardware.camera2.CameraCharacteristics.Key<java.lang.Float> SCALER_AVAILABLE_MAX_DIGITAL_ZOOM;
field @NonNull public static final android.hardware.camera2.CameraCharacteristics.Key<int[]> SCALER_AVAILABLE_ROTATE_AND_CROP_MODES;
- field @NonNull public static final android.hardware.camera2.CameraCharacteristics.Key<int[]> SCALER_AVAILABLE_STREAM_USE_CASES;
+ field @NonNull public static final android.hardware.camera2.CameraCharacteristics.Key<long[]> SCALER_AVAILABLE_STREAM_USE_CASES;
field @NonNull public static final android.hardware.camera2.CameraCharacteristics.Key<java.lang.Integer> SCALER_CROPPING_TYPE;
field @NonNull public static final android.hardware.camera2.CameraCharacteristics.Key<android.util.Size> SCALER_DEFAULT_SECURE_IMAGE_SIZE;
field @NonNull public static final android.hardware.camera2.CameraCharacteristics.Key<android.hardware.camera2.params.MandatoryStreamCombination[]> SCALER_MANDATORY_CONCURRENT_STREAM_COMBINATIONS;
@@ -18193,7 +18232,7 @@
method public int get10BitFormat();
method @NonNull public java.util.List<android.util.Size> getAvailableSizes();
method public int getFormat();
- method public int getStreamUseCase();
+ method public long getStreamUseCase();
method public boolean is10BitCapable();
method public boolean isInput();
method public boolean isMaximumSize();
@@ -18251,7 +18290,7 @@
method public long getDynamicRangeProfile();
method public int getMaxSharedSurfaceCount();
method public int getMirrorMode();
- method public int getStreamUseCase();
+ method public long getStreamUseCase();
method @Nullable public android.view.Surface getSurface();
method public int getSurfaceGroupId();
method @NonNull public java.util.List<android.view.Surface> getSurfaces();
@@ -18261,7 +18300,7 @@
method public void setDynamicRangeProfile(long);
method public void setMirrorMode(int);
method public void setPhysicalCameraId(@Nullable String);
- method public void setStreamUseCase(int);
+ method public void setStreamUseCase(long);
method public void setTimestampBase(int);
method public void writeToParcel(android.os.Parcel, int);
field @NonNull public static final android.os.Parcelable.Creator<android.hardware.camera2.params.OutputConfiguration> CREATOR;
@@ -19473,26 +19512,26 @@
method @NonNull public static String convert(@FloatRange double, int);
method @FloatRange public static double convert(@NonNull String);
method public int describeContents();
- method public static void distanceBetween(@FloatRange double, @FloatRange double, @FloatRange double, @FloatRange double, float[]);
- method @FloatRange public float distanceTo(@NonNull android.location.Location);
- method public void dump(@NonNull android.util.Printer, @Nullable String);
- method @FloatRange public float getAccuracy();
+ method public static void distanceBetween(@FloatRange(from=-90.0, to=90.0) double, @FloatRange(from=-180.0, to=180.0) double, @FloatRange(from=-90.0, to=90.0) double, @FloatRange(from=-180.0, to=180.0) double, float[]);
+ method @FloatRange(from=0.0) public float distanceTo(@NonNull android.location.Location);
+ method @Deprecated public void dump(@NonNull android.util.Printer, @Nullable String);
+ method @FloatRange(from=0.0) public float getAccuracy();
method @FloatRange public double getAltitude();
- method @FloatRange(from=0.0f, to=360.0f, toInclusive=false) public float getBearing();
- method @FloatRange public float getBearingAccuracyDegrees();
- method @IntRange public long getElapsedRealtimeAgeMillis();
- method @IntRange public long getElapsedRealtimeAgeMillis(@IntRange long);
- method @IntRange public long getElapsedRealtimeMillis();
- method @IntRange public long getElapsedRealtimeNanos();
- method @FloatRange public double getElapsedRealtimeUncertaintyNanos();
+ method @FloatRange(from=0.0, to=360.0, toInclusive=false) public float getBearing();
+ method @FloatRange(from=0.0) public float getBearingAccuracyDegrees();
+ method @IntRange(from=0) public long getElapsedRealtimeAgeMillis();
+ method public long getElapsedRealtimeAgeMillis(@IntRange(from=0) long);
+ method @IntRange(from=0) public long getElapsedRealtimeMillis();
+ method @IntRange(from=0) public long getElapsedRealtimeNanos();
+ method @FloatRange(from=0.0) public double getElapsedRealtimeUncertaintyNanos();
method @Nullable public android.os.Bundle getExtras();
- method @FloatRange public double getLatitude();
- method @FloatRange public double getLongitude();
+ method @FloatRange(from=-90.0, to=90.0) public double getLatitude();
+ method @FloatRange(from=-180.0, to=180.0) public double getLongitude();
method @Nullable public String getProvider();
- method @FloatRange public float getSpeed();
- method @FloatRange public float getSpeedAccuracyMetersPerSecond();
- method @IntRange public long getTime();
- method @FloatRange public float getVerticalAccuracyMeters();
+ method @FloatRange(from=0.0) public float getSpeed();
+ method @FloatRange(from=0.0) public float getSpeedAccuracyMetersPerSecond();
+ method @IntRange(from=0) public long getTime();
+ method @FloatRange(from=0.0) public float getVerticalAccuracyMeters();
method public boolean hasAccuracy();
method public boolean hasAltitude();
method public boolean hasBearing();
@@ -19514,21 +19553,21 @@
method public void removeVerticalAccuracy();
method public void reset();
method public void set(@NonNull android.location.Location);
- method public void setAccuracy(@FloatRange float);
+ method public void setAccuracy(@FloatRange(from=0.0) float);
method public void setAltitude(@FloatRange double);
method public void setBearing(@FloatRange(fromInclusive=false, toInclusive=false) float);
- method public void setBearingAccuracyDegrees(@FloatRange float);
- method public void setElapsedRealtimeNanos(@IntRange long);
- method public void setElapsedRealtimeUncertaintyNanos(@FloatRange double);
+ method public void setBearingAccuracyDegrees(@FloatRange(from=0.0) float);
+ method public void setElapsedRealtimeNanos(@IntRange(from=0) long);
+ method public void setElapsedRealtimeUncertaintyNanos(@FloatRange(from=0.0) double);
method public void setExtras(@Nullable android.os.Bundle);
- method public void setLatitude(@FloatRange double);
- method public void setLongitude(@FloatRange double);
+ method public void setLatitude(@FloatRange(from=-90.0, to=90.0) double);
+ method public void setLongitude(@FloatRange(from=-180.0, to=180.0) double);
method public void setMock(boolean);
method public void setProvider(@Nullable String);
- method public void setSpeed(@FloatRange float);
- method public void setSpeedAccuracyMetersPerSecond(@FloatRange float);
- method public void setTime(@IntRange long);
- method public void setVerticalAccuracyMeters(@FloatRange float);
+ method public void setSpeed(@FloatRange(from=0.0) float);
+ method public void setSpeedAccuracyMetersPerSecond(@FloatRange(from=0.0) float);
+ method public void setTime(@IntRange(from=0) long);
+ method public void setVerticalAccuracyMeters(@FloatRange(from=0.0) float);
method public void writeToParcel(@NonNull android.os.Parcel, int);
field @NonNull public static final android.os.Parcelable.Creator<android.location.Location> CREATOR;
field public static final int FORMAT_DEGREES = 0; // 0x0
@@ -22172,7 +22211,7 @@
field public static final String KEY_AAC_DRC_OUTPUT_LOUDNESS = "aac-drc-output-loudness";
field public static final String KEY_AAC_DRC_TARGET_REFERENCE_LEVEL = "aac-target-ref-level";
field public static final String KEY_AAC_ENCODED_TARGET_LEVEL = "aac-encoded-target-level";
- field public static final String KEY_AAC_MAX_OUTPUT_CHANNEL_COUNT = "aac-max-output-channel_count";
+ field @Deprecated public static final String KEY_AAC_MAX_OUTPUT_CHANNEL_COUNT = "aac-max-output-channel_count";
field public static final String KEY_AAC_PROFILE = "aac-profile";
field public static final String KEY_AAC_SBR_MODE = "aac-sbr-mode";
field public static final String KEY_ALLOW_FRAME_DROP = "allow-frame-drop";
@@ -22191,6 +22230,10 @@
field public static final String KEY_COLOR_TRANSFER_REQUEST = "color-transfer-request";
field public static final String KEY_COMPLEXITY = "complexity";
field public static final String KEY_CREATE_INPUT_SURFACE_SUSPENDED = "create-input-buffers-suspended";
+ field public static final String KEY_CROP_BOTTOM = "crop-bottom";
+ field public static final String KEY_CROP_LEFT = "crop-left";
+ field public static final String KEY_CROP_RIGHT = "crop-right";
+ field public static final String KEY_CROP_TOP = "crop-top";
field public static final String KEY_DURATION = "durationUs";
field public static final String KEY_ENCODER_DELAY = "encoder-delay";
field public static final String KEY_ENCODER_PADDING = "encoder-padding";
@@ -22880,7 +22923,6 @@
method public int describeContents();
method @Nullable public String getClientPackageName();
method public int getConnectionState();
- method @NonNull public java.util.Set<java.lang.String> getDeduplicationIds();
method @Nullable public CharSequence getDescription();
method @Nullable public android.os.Bundle getExtras();
method @NonNull public java.util.List<java.lang.String> getFeatures();
@@ -22914,7 +22956,6 @@
method @NonNull public android.media.MediaRoute2Info.Builder clearFeatures();
method @NonNull public android.media.MediaRoute2Info.Builder setClientPackageName(@Nullable String);
method @NonNull public android.media.MediaRoute2Info.Builder setConnectionState(int);
- method @NonNull public android.media.MediaRoute2Info.Builder setDeduplicationIds(@NonNull java.util.Set<java.lang.String>);
method @NonNull public android.media.MediaRoute2Info.Builder setDescription(@Nullable CharSequence);
method @NonNull public android.media.MediaRoute2Info.Builder setExtras(@Nullable android.os.Bundle);
method @NonNull public android.media.MediaRoute2Info.Builder setIconUri(@Nullable android.net.Uri);
@@ -23441,11 +23482,8 @@
public final class RouteDiscoveryPreference implements android.os.Parcelable {
method public int describeContents();
- method @NonNull public java.util.List<java.lang.String> getAllowedPackages();
- method @NonNull public java.util.List<java.lang.String> getDeduplicationPackageOrder();
method @NonNull public java.util.List<java.lang.String> getPreferredFeatures();
method public boolean shouldPerformActiveScan();
- method public boolean shouldRemoveDuplicates();
method public void writeToParcel(@NonNull android.os.Parcel, int);
field @NonNull public static final android.os.Parcelable.Creator<android.media.RouteDiscoveryPreference> CREATOR;
}
@@ -23454,8 +23492,6 @@
ctor public RouteDiscoveryPreference.Builder(@NonNull java.util.List<java.lang.String>, boolean);
ctor public RouteDiscoveryPreference.Builder(@NonNull android.media.RouteDiscoveryPreference);
method @NonNull public android.media.RouteDiscoveryPreference build();
- method @NonNull public android.media.RouteDiscoveryPreference.Builder setAllowedPackages(@NonNull java.util.List<java.lang.String>);
- method @NonNull public android.media.RouteDiscoveryPreference.Builder setDeduplicationPackageOrder(@NonNull java.util.List<java.lang.String>);
method @NonNull public android.media.RouteDiscoveryPreference.Builder setPreferredFeatures(@NonNull java.util.List<java.lang.String>);
method @NonNull public android.media.RouteDiscoveryPreference.Builder setShouldPerformActiveScan(boolean);
}
@@ -23534,17 +23570,24 @@
}
public class Spatializer {
+ method public void addOnHeadTrackerAvailableListener(@NonNull java.util.concurrent.Executor, @NonNull android.media.Spatializer.OnHeadTrackerAvailableListener);
method public void addOnSpatializerStateChangedListener(@NonNull java.util.concurrent.Executor, @NonNull android.media.Spatializer.OnSpatializerStateChangedListener);
method public boolean canBeSpatialized(@NonNull android.media.AudioAttributes, @NonNull android.media.AudioFormat);
method public int getImmersiveAudioLevel();
method public boolean isAvailable();
method public boolean isEnabled();
+ method public boolean isHeadTrackerAvailable();
+ method public void removeOnHeadTrackerAvailableListener(@NonNull android.media.Spatializer.OnHeadTrackerAvailableListener);
method public void removeOnSpatializerStateChangedListener(@NonNull android.media.Spatializer.OnSpatializerStateChangedListener);
field public static final int SPATIALIZER_IMMERSIVE_LEVEL_MULTICHANNEL = 1; // 0x1
field public static final int SPATIALIZER_IMMERSIVE_LEVEL_NONE = 0; // 0x0
field public static final int SPATIALIZER_IMMERSIVE_LEVEL_OTHER = -1; // 0xffffffff
}
+ public static interface Spatializer.OnHeadTrackerAvailableListener {
+ method public void onHeadTrackerAvailableChanged(@NonNull android.media.Spatializer, boolean);
+ }
+
public static interface Spatializer.OnSpatializerStateChangedListener {
method public void onSpatializerAvailableChanged(@NonNull android.media.Spatializer, boolean);
method public void onSpatializerEnabledChanged(@NonNull android.media.Spatializer, boolean);
@@ -25177,17 +25220,23 @@
}
public final class CommandRequest extends android.media.tv.BroadcastInfoRequest implements android.os.Parcelable {
- ctor public CommandRequest(int, int, @NonNull String, @NonNull String, @NonNull String);
+ ctor public CommandRequest(int, int, @NonNull String, @NonNull String, @NonNull String, @NonNull String);
+ method @NonNull public String getArgumentType();
method @NonNull public String getArguments();
method @NonNull public String getName();
- method @NonNull public String getNameSpace();
+ method @NonNull public String getNamespace();
+ field public static final String ARGUMENT_TYPE_JSON = "json";
+ field public static final String ARGUMENT_TYPE_XML = "xml";
field @NonNull public static final android.os.Parcelable.Creator<android.media.tv.CommandRequest> CREATOR;
}
public final class CommandResponse extends android.media.tv.BroadcastInfoResponse implements android.os.Parcelable {
- ctor public CommandResponse(int, int, int, @Nullable String);
+ ctor public CommandResponse(int, int, int, @Nullable String, @NonNull String);
method @Nullable public String getResponse();
+ method @NonNull public String getResponseType();
field @NonNull public static final android.os.Parcelable.Creator<android.media.tv.CommandResponse> CREATOR;
+ field public static final String RESPONSE_TYPE_JSON = "json";
+ field public static final String RESPONSE_TYPE_XML = "xml";
}
public final class DsmccRequest extends android.media.tv.BroadcastInfoRequest implements android.os.Parcelable {
@@ -25252,7 +25301,7 @@
ctor public StreamEventResponse(int, int, int, int, long, @Nullable byte[]);
method @Nullable public byte[] getData();
method public int getEventId();
- method public long getNpt();
+ method public long getNptMillis();
field @NonNull public static final android.os.Parcelable.Creator<android.media.tv.StreamEventResponse> CREATOR;
}
@@ -25282,7 +25331,7 @@
public final class TimelineResponse extends android.media.tv.BroadcastInfoResponse implements android.os.Parcelable {
ctor public TimelineResponse(int, int, int, @Nullable String, int, int, long, long);
- method @Nullable public String getSelector();
+ method @Nullable public android.net.Uri getSelector();
method public long getTicks();
method public int getUnitsPerSecond();
method public int getUnitsPerTick();
@@ -26045,7 +26094,7 @@
method public void onContentAllowed(String);
method public void onContentBlocked(String, android.media.tv.TvContentRating);
method public void onDisconnected(String);
- method public void onSignalStrength(@NonNull String, int);
+ method public void onSignalStrengthUpdated(@NonNull String, int);
method public void onTimeShiftStatusChanged(String, int);
method public void onTrackSelected(String, int, String);
method public void onTracksChanged(String, java.util.List<android.media.tv.TvTrackInfo>);
@@ -26060,40 +26109,16 @@
package android.media.tv.interactive {
public final class AppLinkInfo implements android.os.Parcelable {
+ ctor public AppLinkInfo(@NonNull String, @NonNull String, @NonNull String);
method public int describeContents();
- method @NonNull public String getClassName();
- method @NonNull public String getPackageName();
- method @Nullable public String getUriHost();
- method @Nullable public String getUriPrefix();
- method @Nullable public String getUriScheme();
+ method @NonNull public android.content.ComponentName getComponentName();
+ method @NonNull public android.net.Uri getUri();
method public void writeToParcel(@NonNull android.os.Parcel, int);
field @NonNull public static final android.os.Parcelable.Creator<android.media.tv.interactive.AppLinkInfo> CREATOR;
}
- public static final class AppLinkInfo.Builder {
- ctor public AppLinkInfo.Builder(@NonNull String, @NonNull String);
- method @NonNull public android.media.tv.interactive.AppLinkInfo build();
- method @NonNull public android.media.tv.interactive.AppLinkInfo.Builder setUriHost(@NonNull String);
- method @NonNull public android.media.tv.interactive.AppLinkInfo.Builder setUriPrefix(@NonNull String);
- method @NonNull public android.media.tv.interactive.AppLinkInfo.Builder setUriScheme(@NonNull String);
- }
-
- public final class TvInteractiveAppInfo implements android.os.Parcelable {
- ctor public TvInteractiveAppInfo(@NonNull android.content.Context, @NonNull android.content.ComponentName);
- method public int describeContents();
- method @NonNull public String getId();
- method @Nullable public android.content.pm.ServiceInfo getServiceInfo();
- method @NonNull public int getSupportedTypes();
- method public void writeToParcel(@NonNull android.os.Parcel, int);
- field @NonNull public static final android.os.Parcelable.Creator<android.media.tv.interactive.TvInteractiveAppInfo> CREATOR;
- field public static final int INTERACTIVE_APP_TYPE_ATSC = 2; // 0x2
- field public static final int INTERACTIVE_APP_TYPE_GINGA = 4; // 0x4
- field public static final int INTERACTIVE_APP_TYPE_HBBTV = 1; // 0x1
- }
-
public final class TvInteractiveAppManager {
- method @NonNull public java.util.List<android.media.tv.interactive.TvInteractiveAppInfo> getTvInteractiveAppServiceList();
- method public void prepare(@NonNull String, int);
+ method @NonNull public java.util.List<android.media.tv.interactive.TvInteractiveAppServiceInfo> getTvInteractiveAppServiceList();
method public void registerAppLinkInfo(@NonNull String, @NonNull android.media.tv.interactive.AppLinkInfo);
method public void registerCallback(@NonNull java.util.concurrent.Executor, @NonNull android.media.tv.interactive.TvInteractiveAppManager.TvInteractiveAppCallback);
method public void sendAppLinkCommand(@NonNull String, @NonNull android.os.Bundle);
@@ -26116,6 +26141,7 @@
field public static final String INTENT_KEY_BI_INTERACTIVE_APP_TYPE = "bi_interactive_app_type";
field public static final String INTENT_KEY_BI_INTERACTIVE_APP_URI = "bi_interactive_app_uri";
field public static final String INTENT_KEY_CHANNEL_URI = "channel_uri";
+ field public static final String INTENT_KEY_COMMAND_TYPE = "command_type";
field public static final String INTENT_KEY_INTERACTIVE_APP_SERVICE_ID = "interactive_app_id";
field public static final String INTENT_KEY_TV_INPUT_ID = "tv_input_id";
field public static final int INTERACTIVE_APP_STATE_ERROR = 3; // 0x3
@@ -26144,7 +26170,6 @@
method public void onAppLinkCommand(@NonNull android.os.Bundle);
method @Nullable public final android.os.IBinder onBind(@NonNull android.content.Intent);
method @Nullable public abstract android.media.tv.interactive.TvInteractiveAppService.Session onCreateSession(@NonNull String, int);
- method public abstract void onPrepare(int);
method public void onRegisterAppLinkInfo(@NonNull android.media.tv.interactive.AppLinkInfo);
method public void onUnregisterAppLinkInfo(@NonNull android.media.tv.interactive.AppLinkInfo);
field public static final String COMMAND_PARAMETER_KEY_CHANGE_CHANNEL_QUIETLY = "command_change_channel_quietly";
@@ -26165,6 +26190,7 @@
public abstract static class TvInteractiveAppService.Session implements android.view.KeyEvent.Callback {
ctor public TvInteractiveAppService.Session(@NonNull android.content.Context);
+ method public boolean isMediaViewEnabled();
method @CallSuper public void layoutSurface(int, int, int, int);
method @CallSuper public final void notifyBiInteractiveAppCreated(@NonNull android.net.Uri, @Nullable String);
method @CallSuper public void notifySessionStateChanged(int, int);
@@ -26173,23 +26199,24 @@
method public void onBroadcastInfoResponse(@NonNull android.media.tv.BroadcastInfoResponse);
method public void onContentAllowed();
method public void onContentBlocked(@NonNull android.media.tv.TvContentRating);
- method public void onCreateBiInteractiveApp(@NonNull android.net.Uri, @Nullable android.os.Bundle);
+ method public void onCreateBiInteractiveAppRequest(@NonNull android.net.Uri, @Nullable android.os.Bundle);
method @Nullable public android.view.View onCreateMediaView();
method public void onCurrentChannelLcn(int);
method public void onCurrentChannelUri(@Nullable android.net.Uri);
method public void onCurrentTvInputId(@Nullable String);
- method public void onDestroyBiInteractiveApp(@NonNull String);
+ method public void onDestroyBiInteractiveAppRequest(@NonNull String);
method public boolean onGenericMotionEvent(@NonNull android.view.MotionEvent);
method public boolean onKeyDown(int, @NonNull android.view.KeyEvent);
method public boolean onKeyLongPress(int, @NonNull android.view.KeyEvent);
method public boolean onKeyMultiple(int, int, @NonNull android.view.KeyEvent);
method public boolean onKeyUp(int, @NonNull android.view.KeyEvent);
- method public void onMediaViewSizeChanged(int, int);
+ method public void onMediaViewSizeChanged(@Px int, @Px int);
method public abstract void onRelease();
method public void onResetInteractiveApp();
method public abstract boolean onSetSurface(@Nullable android.view.Surface);
method public void onSetTeletextAppEnabled(boolean);
method public void onSignalStrength(int);
+ method public void onSigningResult(@NonNull String, @NonNull byte[]);
method public void onStartInteractiveApp();
method public void onStopInteractiveApp();
method public void onStreamVolume(float);
@@ -26208,6 +26235,7 @@
method @CallSuper public void requestCurrentChannelLcn();
method @CallSuper public void requestCurrentChannelUri();
method @CallSuper public void requestCurrentTvInputId();
+ method @CallSuper public void requestSigning(@NonNull String, @NonNull String, @NonNull String, @NonNull byte[]);
method @CallSuper public void requestStreamVolume();
method @CallSuper public void requestTrackInfoList();
method @CallSuper public void sendPlaybackCommandRequest(@NonNull String, @Nullable android.os.Bundle);
@@ -26215,6 +26243,19 @@
method @CallSuper public void setVideoBounds(@NonNull android.graphics.Rect);
}
+ public final class TvInteractiveAppServiceInfo implements android.os.Parcelable {
+ ctor public TvInteractiveAppServiceInfo(@NonNull android.content.Context, @NonNull android.content.ComponentName);
+ method public int describeContents();
+ method @NonNull public String getId();
+ method @Nullable public android.content.pm.ServiceInfo getServiceInfo();
+ method @NonNull public int getSupportedTypes();
+ method public void writeToParcel(@NonNull android.os.Parcel, int);
+ field @NonNull public static final android.os.Parcelable.Creator<android.media.tv.interactive.TvInteractiveAppServiceInfo> CREATOR;
+ field public static final int INTERACTIVE_APP_TYPE_ATSC = 2; // 0x2
+ field public static final int INTERACTIVE_APP_TYPE_GINGA = 4; // 0x4
+ field public static final int INTERACTIVE_APP_TYPE_HBBTV = 1; // 0x1
+ }
+
public class TvInteractiveAppView extends android.view.ViewGroup {
ctor public TvInteractiveAppView(@NonNull android.content.Context);
ctor public TvInteractiveAppView(@NonNull android.content.Context, @Nullable android.util.AttributeSet);
@@ -26224,6 +26265,7 @@
method public void createBiInteractiveApp(@NonNull android.net.Uri, @Nullable android.os.Bundle);
method public void destroyBiInteractiveApp(@NonNull String);
method public boolean dispatchUnhandledInputEvent(@NonNull android.view.InputEvent);
+ method @Nullable public android.media.tv.interactive.TvInteractiveAppView.OnUnhandledInputEventListener getOnUnhandledInputEventListener();
method public void onAttachedToWindow();
method public void onDetachedFromWindow();
method public void onLayout(boolean, int, int, int, int);
@@ -26236,6 +26278,7 @@
method public void sendCurrentChannelLcn(int);
method public void sendCurrentChannelUri(@Nullable android.net.Uri);
method public void sendCurrentTvInputId(@Nullable String);
+ method public void sendSigningResult(@NonNull String, @NonNull byte[]);
method public void sendStreamVolume(float);
method public void sendTrackInfoList(@Nullable java.util.List<android.media.tv.TvTrackInfo>);
method public void setCallback(@NonNull java.util.concurrent.Executor, @NonNull android.media.tv.interactive.TvInteractiveAppView.TvInteractiveAppCallback);
@@ -26244,6 +26287,11 @@
method public int setTvView(@Nullable android.media.tv.TvView);
method public void startInteractiveApp();
method public void stopInteractiveApp();
+ field public static final String BI_INTERACTIVE_APP_KEY_ALIAS = "alias";
+ field public static final String BI_INTERACTIVE_APP_KEY_CERTIFICATE = "certificate";
+ field public static final String BI_INTERACTIVE_APP_KEY_HTTP_ADDITIONAL_HEADERS = "http_additional_headers";
+ field public static final String BI_INTERACTIVE_APP_KEY_HTTP_USER_AGENT = "http_user_agent";
+ field public static final String BI_INTERACTIVE_APP_KEY_PRIVATE_KEY = "private_key";
}
public static interface TvInteractiveAppView.OnUnhandledInputEventListener {
@@ -26257,6 +26305,7 @@
method public void onRequestCurrentChannelLcn(@NonNull String);
method public void onRequestCurrentChannelUri(@NonNull String);
method public void onRequestCurrentTvInputId(@NonNull String);
+ method public void onRequestSigning(@NonNull String, @NonNull String, @NonNull String, @NonNull String, @NonNull byte[]);
method public void onRequestStreamVolume(@NonNull String);
method public void onRequestTrackInfoList(@NonNull String);
method public void onSetVideoBounds(@NonNull String, @NonNull android.graphics.Rect);
@@ -26517,6 +26566,7 @@
public final class Ikev2VpnProfile extends android.net.PlatformVpnProfile {
method @NonNull public java.util.List<java.lang.String> getAllowedAlgorithms();
+ method @Nullable public android.net.ipsec.ike.IkeTunnelConnectionParams getIkeTunnelConnectionParams();
method public int getMaxMtu();
method @Nullable public String getPassword();
method @Nullable public byte[] getPresharedKey();
@@ -26811,11 +26861,13 @@
public class VpnManager {
method public void deleteProvisionedVpnProfile();
+ method @Nullable public android.net.VpnProfileState getProvisionedVpnProfileState();
method @Nullable public android.content.Intent provisionVpnProfile(@NonNull android.net.PlatformVpnProfile);
method @Deprecated public void startProvisionedVpnProfile();
method @NonNull public String startProvisionedVpnProfileSession();
method public void stopProvisionedVpnProfile();
field public static final String ACTION_VPN_MANAGER_EVENT = "android.net.action.VPN_MANAGER_EVENT";
+ field public static final String CATEGORY_EVENT_ALWAYS_ON_STATE_CHANGED = "android.net.category.EVENT_ALWAYS_ON_STATE_CHANGED";
field public static final String CATEGORY_EVENT_DEACTIVATED_BY_USER = "android.net.category.EVENT_DEACTIVATED_BY_USER";
field public static final String CATEGORY_EVENT_IKE_ERROR = "android.net.category.EVENT_IKE_ERROR";
field public static final String CATEGORY_EVENT_NETWORK_ERROR = "android.net.category.EVENT_NETWORK_ERROR";
@@ -26832,6 +26884,22 @@
field public static final String EXTRA_UNDERLYING_LINK_PROPERTIES = "android.net.extra.UNDERLYING_LINK_PROPERTIES";
field public static final String EXTRA_UNDERLYING_NETWORK = "android.net.extra.UNDERLYING_NETWORK";
field public static final String EXTRA_UNDERLYING_NETWORK_CAPABILITIES = "android.net.extra.UNDERLYING_NETWORK_CAPABILITIES";
+ field public static final String EXTRA_VPN_PROFILE_STATE = "android.net.extra.VPN_PROFILE_STATE";
+ }
+
+ public final class VpnProfileState implements android.os.Parcelable {
+ ctor public VpnProfileState(int, @Nullable String, boolean, boolean);
+ method public int describeContents();
+ method @Nullable public String getSessionId();
+ method public int getState();
+ method public boolean isAlwaysOn();
+ method public boolean isLockdownEnabled();
+ method public void writeToParcel(@NonNull android.os.Parcel, int);
+ field @NonNull public static final android.os.Parcelable.Creator<android.net.VpnProfileState> CREATOR;
+ field public static final int STATE_CONNECTED = 2; // 0x2
+ field public static final int STATE_CONNECTING = 1; // 0x1
+ field public static final int STATE_DISCONNECTED = 0; // 0x0
+ field public static final int STATE_FAILED = 3; // 0x3
}
public class VpnService extends android.app.Service {
@@ -38160,6 +38228,7 @@
field @NonNull public static final android.os.Parcelable.Creator<android.service.autofill.FillRequest> CREATOR;
field public static final int FLAG_COMPATIBILITY_MODE_REQUEST = 2; // 0x2
field public static final int FLAG_MANUAL_REQUEST = 1; // 0x1
+ field public static final int FLAG_SUPPORTS_FILL_DIALOG = 64; // 0x40
}
public final class FillResponse implements android.os.Parcelable {
@@ -43782,6 +43851,7 @@
method public int getNetworkTypeBitmask();
method public String getOperatorNumeric();
method public String getPassword();
+ method public int getProfileId();
method public int getProtocol();
method @Deprecated public java.net.InetAddress getProxyAddress();
method public String getProxyAddressAsString();
@@ -43789,6 +43859,7 @@
method public int getRoamingProtocol();
method public String getUser();
method public boolean isEnabled();
+ method public boolean isPersistent();
method public void writeToParcel(@NonNull android.os.Parcel, int);
field public static final int AUTH_TYPE_CHAP = 2; // 0x2
field public static final int AUTH_TYPE_NONE = 0; // 0x0
@@ -45062,7 +45133,7 @@
public static final class PrecomputedText.Params {
method public int getBreakStrategy();
method public int getHyphenationFrequency();
- method @Nullable public android.graphics.text.LineBreakConfig getLineBreakConfig();
+ method @NonNull public android.graphics.text.LineBreakConfig getLineBreakConfig();
method @NonNull public android.text.TextDirectionHeuristic getTextDirection();
method @NonNull public android.text.TextPaint getTextPaint();
}
@@ -49276,6 +49347,7 @@
method @NonNull public android.view.SurfaceControl.Transaction setAlpha(@NonNull android.view.SurfaceControl, @FloatRange(from=0.0, to=1.0) float);
method @NonNull public android.view.SurfaceControl.Transaction setBuffer(@NonNull android.view.SurfaceControl, @Nullable android.hardware.HardwareBuffer);
method @NonNull public android.view.SurfaceControl.Transaction setBuffer(@NonNull android.view.SurfaceControl, @Nullable android.hardware.HardwareBuffer, @Nullable android.hardware.SyncFence);
+ method @NonNull public android.view.SurfaceControl.Transaction setBuffer(@NonNull android.view.SurfaceControl, @Nullable android.hardware.HardwareBuffer, @Nullable android.hardware.SyncFence, @Nullable java.util.function.Consumer<android.hardware.SyncFence>);
method @NonNull public android.view.SurfaceControl.Transaction setBufferSize(@NonNull android.view.SurfaceControl, @IntRange(from=0) int, @IntRange(from=0) int);
method @NonNull public android.view.SurfaceControl.Transaction setBufferTransform(@NonNull android.view.SurfaceControl, int);
method @NonNull public android.view.SurfaceControl.Transaction setCrop(@NonNull android.view.SurfaceControl, @Nullable android.graphics.Rect);
@@ -57352,7 +57424,8 @@
method public final android.text.Layout getLayout();
method public float getLetterSpacing();
method public int getLineBounds(int, android.graphics.Rect);
- method @NonNull public android.graphics.text.LineBreakConfig getLineBreakConfig();
+ method public int getLineBreakStyle();
+ method public int getLineBreakWordStyle();
method public int getLineCount();
method public int getLineHeight();
method public float getLineSpacingExtra();
@@ -57480,7 +57553,8 @@
method public void setKeyListener(android.text.method.KeyListener);
method public void setLastBaselineToBottomHeight(@IntRange(from=0) @Px int);
method public void setLetterSpacing(float);
- method public void setLineBreakConfig(@NonNull android.graphics.text.LineBreakConfig);
+ method public void setLineBreakStyle(int);
+ method public void setLineBreakWordStyle(int);
method public void setLineHeight(@IntRange(from=0) @Px int);
method public void setLineSpacing(float, float);
method public void setLines(int);
@@ -57890,7 +57964,7 @@
}
public interface OnBackInvokedDispatcher {
- method public void registerOnBackInvokedCallback(@NonNull android.window.OnBackInvokedCallback, @IntRange(from=0) int);
+ method public void registerOnBackInvokedCallback(@IntRange(from=0) int, @NonNull android.window.OnBackInvokedCallback);
method public void unregisterOnBackInvokedCallback(@NonNull android.window.OnBackInvokedCallback);
field public static final int PRIORITY_DEFAULT = 0; // 0x0
field public static final int PRIORITY_OVERLAY = 1000000; // 0xf4240
diff --git a/core/api/module-lib-current.txt b/core/api/module-lib-current.txt
index 3d5232b..d2cc0f5 100644
--- a/core/api/module-lib-current.txt
+++ b/core/api/module-lib-current.txt
@@ -243,7 +243,8 @@
method @Nullable @RequiresPermission(anyOf={android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK, android.Manifest.permission.NETWORK_STACK}) public android.telephony.SubscriptionPlan getSubscriptionPlan(@NonNull android.net.NetworkTemplate);
method @RequiresPermission(android.Manifest.permission.OBSERVE_NETWORK_POLICY) public boolean isUidNetworkingBlocked(int, boolean);
method @RequiresPermission(android.Manifest.permission.OBSERVE_NETWORK_POLICY) public boolean isUidRestrictedOnMeteredNetworks(int);
- method @RequiresPermission(anyOf={android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK, android.Manifest.permission.NETWORK_STACK}) public void notifyStatsProviderWarningOrLimitReached();
+ method @RequiresPermission(anyOf={android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK, android.Manifest.permission.NETWORK_STACK}) public void notifyStatsProviderLimitReached();
+ method @RequiresPermission(anyOf={android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK, android.Manifest.permission.NETWORK_STACK}) public void notifyStatsProviderWarningReached();
method @RequiresPermission(android.Manifest.permission.OBSERVE_NETWORK_POLICY) public void registerNetworkPolicyCallback(@Nullable java.util.concurrent.Executor, @NonNull android.net.NetworkPolicyManager.NetworkPolicyCallback);
method @RequiresPermission(android.Manifest.permission.OBSERVE_NETWORK_POLICY) public void unregisterNetworkPolicyCallback(@NonNull android.net.NetworkPolicyManager.NetworkPolicyCallback);
}
diff --git a/core/api/system-current.txt b/core/api/system-current.txt
index 09d1114..94efd92 100644
--- a/core/api/system-current.txt
+++ b/core/api/system-current.txt
@@ -5,6 +5,7 @@
field public static final String ACCESS_AMBIENT_CONTEXT_EVENT = "android.permission.ACCESS_AMBIENT_CONTEXT_EVENT";
field public static final String ACCESS_AMBIENT_LIGHT_STATS = "android.permission.ACCESS_AMBIENT_LIGHT_STATS";
field public static final String ACCESS_BROADCAST_RADIO = "android.permission.ACCESS_BROADCAST_RADIO";
+ field public static final String ACCESS_BROADCAST_RESPONSE_STATS = "android.permission.ACCESS_BROADCAST_RESPONSE_STATS";
field public static final String ACCESS_CACHE_FILESYSTEM = "android.permission.ACCESS_CACHE_FILESYSTEM";
field public static final String ACCESS_CONTEXT_HUB = "android.permission.ACCESS_CONTEXT_HUB";
field public static final String ACCESS_DRM_CERTIFICATES = "android.permission.ACCESS_DRM_CERTIFICATES";
@@ -244,6 +245,7 @@
field public static final String READ_APP_SPECIFIC_LOCALES = "android.permission.READ_APP_SPECIFIC_LOCALES";
field public static final String READ_CARRIER_APP_INFO = "android.permission.READ_CARRIER_APP_INFO";
field public static final String READ_CELL_BROADCASTS = "android.permission.READ_CELL_BROADCASTS";
+ field public static final String READ_CLIPBOARD_IN_BACKGROUND = "android.permission.READ_CLIPBOARD_IN_BACKGROUND";
field public static final String READ_CONTENT_RATING_SYSTEMS = "android.permission.READ_CONTENT_RATING_SYSTEMS";
field public static final String READ_DEVICE_CONFIG = "android.permission.READ_DEVICE_CONFIG";
field public static final String READ_DREAM_STATE = "android.permission.READ_DREAM_STATE";
@@ -1079,6 +1081,7 @@
method @RequiresPermission(android.Manifest.permission.MANAGE_PROFILE_AND_DEVICE_OWNERS) public int checkProvisioningPrecondition(@NonNull String, @NonNull String);
method @Nullable @RequiresPermission(android.Manifest.permission.MANAGE_PROFILE_AND_DEVICE_OWNERS) public android.os.UserHandle createAndProvisionManagedProfile(@NonNull android.app.admin.ManagedProfileProvisioningParams) throws android.app.admin.ProvisioningException;
method @Nullable public android.content.Intent createProvisioningIntentFromNfcIntent(@NonNull android.content.Intent);
+ method @RequiresPermission(android.Manifest.permission.MANAGE_PROFILE_AND_DEVICE_OWNERS) public void finalizeWorkProfileProvisioning(@NonNull android.os.UserHandle, @Nullable android.accounts.Account);
method @RequiresPermission(android.Manifest.permission.INTERACT_ACROSS_USERS) public boolean getBluetoothContactSharingDisabled(@NonNull android.os.UserHandle);
method @Nullable @RequiresPermission(android.Manifest.permission.MANAGE_USERS) public String getDeviceOwner();
method @RequiresPermission(anyOf={android.Manifest.permission.MANAGE_USERS, android.Manifest.permission.MANAGE_PROFILE_AND_DEVICE_OWNERS}) public android.content.ComponentName getDeviceOwnerComponentOnAnyUser();
@@ -1089,8 +1092,6 @@
method @Nullable @RequiresPermission(anyOf={android.Manifest.permission.MANAGE_USERS, android.Manifest.permission.QUERY_ADMIN_POLICY}) public java.util.List<java.lang.String> getPermittedInputMethodsForCurrentUser();
method @Nullable public android.content.ComponentName getProfileOwner() throws java.lang.IllegalArgumentException;
method @Nullable @RequiresPermission(anyOf={android.Manifest.permission.MANAGE_USERS, android.Manifest.permission.MANAGE_PROFILE_AND_DEVICE_OWNERS}) public String getProfileOwnerNameAsUser(int) throws java.lang.IllegalArgumentException;
- method @Nullable public String getString(@NonNull String, @NonNull java.util.function.Supplier<java.lang.String>);
- method @Nullable public String getString(@NonNull String, @NonNull java.util.function.Supplier<java.lang.String>, @NonNull java.lang.Object...);
method @RequiresPermission(anyOf={android.Manifest.permission.MANAGE_USERS, android.Manifest.permission.MANAGE_PROFILE_AND_DEVICE_OWNERS}) public int getUserProvisioningState();
method public boolean isDeviceManaged();
method @RequiresPermission(android.Manifest.permission.MANAGE_USERS) public boolean isDeviceProvisioned();
@@ -1103,17 +1104,14 @@
method @RequiresPermission("android.permission.NOTIFY_PENDING_SYSTEM_UPDATE") public void notifyPendingSystemUpdate(long, boolean);
method @RequiresPermission(android.Manifest.permission.INTERACT_ACROSS_USERS_FULL) public boolean packageHasActiveAdmins(String);
method @RequiresPermission(anyOf={android.Manifest.permission.MANAGE_PROFILE_AND_DEVICE_OWNERS, android.Manifest.permission.PROVISION_DEMO_DEVICE}) public void provisionFullyManagedDevice(@NonNull android.app.admin.FullyManagedDeviceProvisioningParams) throws android.app.admin.ProvisioningException;
- method @RequiresPermission(android.Manifest.permission.UPDATE_DEVICE_MANAGEMENT_RESOURCES) public void resetDrawables(@NonNull String[]);
- method @RequiresPermission(android.Manifest.permission.UPDATE_DEVICE_MANAGEMENT_RESOURCES) public void resetStrings(@NonNull String[]);
method @RequiresPermission(android.Manifest.permission.SEND_LOST_MODE_LOCATION_UPDATES) public void sendLostModeLocationUpdate(@NonNull java.util.concurrent.Executor, @NonNull java.util.function.Consumer<java.lang.Boolean>);
method @Deprecated @RequiresPermission(android.Manifest.permission.MANAGE_DEVICE_ADMINS) public boolean setActiveProfileOwner(@NonNull android.content.ComponentName, String) throws java.lang.IllegalArgumentException;
method @RequiresPermission(android.Manifest.permission.MANAGE_USERS) public void setDeviceProvisioningConfigApplied();
method @RequiresPermission(android.Manifest.permission.MANAGE_PROFILE_AND_DEVICE_OWNERS) public void setDpcDownloaded(boolean);
- method @RequiresPermission(android.Manifest.permission.UPDATE_DEVICE_MANAGEMENT_RESOURCES) public void setDrawables(@NonNull java.util.Set<android.app.admin.DevicePolicyDrawableResource>);
method @Deprecated @RequiresPermission(value=android.Manifest.permission.GRANT_PROFILE_OWNER_DEVICE_IDS_ACCESS, conditional=true) public void setProfileOwnerCanAccessDeviceIds(@NonNull android.content.ComponentName);
method public void setSecondaryLockscreenEnabled(@NonNull android.content.ComponentName, boolean);
- method @RequiresPermission(android.Manifest.permission.UPDATE_DEVICE_MANAGEMENT_RESOURCES) public void setStrings(@NonNull java.util.Set<android.app.admin.DevicePolicyStringResource>);
method @RequiresPermission(android.Manifest.permission.MANAGE_PROFILE_AND_DEVICE_OWNERS) public void setUserProvisioningState(int, @NonNull android.os.UserHandle);
+ method @RequiresPermission(android.Manifest.permission.MANAGE_ROLE_HOLDERS) public boolean shouldAllowBypassingDevicePolicyManagementRoleQualification();
field public static final String ACCOUNT_FEATURE_DEVICE_OR_PROFILE_OWNER_ALLOWED = "android.account.DEVICE_OR_PROFILE_OWNER_ALLOWED";
field public static final String ACCOUNT_FEATURE_DEVICE_OR_PROFILE_OWNER_DISALLOWED = "android.account.DEVICE_OR_PROFILE_OWNER_DISALLOWED";
field public static final String ACTION_BIND_SECONDARY_LOCKSCREEN_SERVICE = "android.app.action.BIND_SECONDARY_LOCKSCREEN_SERVICE";
@@ -1128,7 +1126,7 @@
field @RequiresPermission(android.Manifest.permission.LAUNCH_DEVICE_MANAGER_SETUP) public static final String ACTION_ROLE_HOLDER_PROVISION_MANAGED_PROFILE = "android.app.action.ROLE_HOLDER_PROVISION_MANAGED_PROFILE";
field public static final String ACTION_SET_PROFILE_OWNER = "android.app.action.SET_PROFILE_OWNER";
field @Deprecated public static final String ACTION_STATE_USER_SETUP_COMPLETE = "android.app.action.STATE_USER_SETUP_COMPLETE";
- field @RequiresPermission(android.Manifest.permission.LAUNCH_DEVICE_MANAGER_SETUP) public static final String ACTION_UPDATE_DEVICE_MANAGEMENT_ROLE_HOLDER = "android.app.action.UPDATE_DEVICE_MANAGEMENT_ROLE_HOLDER";
+ field @RequiresPermission(android.Manifest.permission.LAUNCH_DEVICE_MANAGER_SETUP) public static final String ACTION_UPDATE_DEVICE_POLICY_MANAGEMENT_ROLE_HOLDER = "android.app.action.UPDATE_DEVICE_POLICY_MANAGEMENT_ROLE_HOLDER";
field public static final String EXTRA_FORCE_UPDATE_ROLE_HOLDER = "android.app.extra.FORCE_UPDATE_ROLE_HOLDER";
field public static final String EXTRA_LOST_MODE_LOCATION = "android.app.extra.LOST_MODE_LOCATION";
field public static final String EXTRA_PROFILE_OWNER_NAME = "android.app.extra.PROFILE_OWNER_NAME";
@@ -1148,6 +1146,7 @@
field public static final String EXTRA_RESTRICTION = "android.app.extra.RESTRICTION";
field public static final String EXTRA_ROLE_HOLDER_PROVISIONING_INITIATOR_PACKAGE = "android.app.extra.ROLE_HOLDER_PROVISIONING_INITIATOR_PACKAGE";
field public static final String EXTRA_ROLE_HOLDER_STATE = "android.app.extra.ROLE_HOLDER_STATE";
+ field public static final String EXTRA_ROLE_HOLDER_UPDATE_RESULT_CODE = "android.app.extra.ROLE_HOLDER_UPDATE_RESULT_CODE";
field public static final int FLAG_SUPPORTED_MODES_DEVICE_OWNER = 4; // 0x4
field public static final int FLAG_SUPPORTED_MODES_ORGANIZATION_OWNED = 1; // 0x1
field public static final int FLAG_SUPPORTED_MODES_PERSONALLY_OWNED = 2; // 0x2
@@ -1161,8 +1160,9 @@
field public static final String REQUIRED_APP_MANAGED_PROFILE = "android.app.REQUIRED_APP_MANAGED_PROFILE";
field public static final String REQUIRED_APP_MANAGED_USER = "android.app.REQUIRED_APP_MANAGED_USER";
field public static final int RESULT_DEVICE_OWNER_SET = 123; // 0x7b
- field public static final int RESULT_UPDATE_DEVICE_MANAGEMENT_ROLE_HOLDER_RECOVERABLE_ERROR = 1; // 0x1
- field public static final int RESULT_UPDATE_DEVICE_MANAGEMENT_ROLE_HOLDER_UNRECOVERABLE_ERROR = 2; // 0x2
+ field public static final int RESULT_UPDATE_DEVICE_POLICY_MANAGEMENT_ROLE_HOLDER_PROVISIONING_DISABLED = 3; // 0x3
+ field public static final int RESULT_UPDATE_DEVICE_POLICY_MANAGEMENT_ROLE_HOLDER_RECOVERABLE_ERROR = 1; // 0x1
+ field public static final int RESULT_UPDATE_DEVICE_POLICY_MANAGEMENT_ROLE_HOLDER_UNRECOVERABLE_ERROR = 2; // 0x2
field public static final int RESULT_UPDATE_ROLE_HOLDER = 2; // 0x2
field public static final int RESULT_WORK_PROFILE_CREATED = 122; // 0x7a
field public static final int STATE_USER_PROFILE_COMPLETE = 4; // 0x4
@@ -1189,43 +1189,6 @@
}
public static final class DevicePolicyResources.Strings {
- field public static final String UNDEFINED = "UNDEFINED";
- }
-
- public static final class DevicePolicyResources.Strings.Dialer {
- field public static final String NOTIFICATION_INCOMING_WORK_CALL_TITLE = "Dialer.NOTIFICATION_INCOMING_WORK_CALL_TITLE";
- field public static final String NOTIFICATION_MISSED_WORK_CALL_TITLE = "Dialer.NOTIFICATION_MISSED_WORK_CALL_TITLE";
- field public static final String NOTIFICATION_ONGOING_WORK_CALL_TITLE = "Dialer.NOTIFICATION_ONGOING_WORK_CALL_TITLE";
- field public static final String NOTIFICATION_WIFI_WORK_CALL_LABEL = "Dialer.NOTIFICATION_WIFI_WORK_CALL_LABEL";
- }
-
- public static final class DevicePolicyResources.Strings.DocumentsUi {
- field public static final String CANT_SAVE_TO_PERSONAL_MESSAGE = "DocumentsUi.CANT_SAVE_TO_PERSONAL_MESSAGE";
- field public static final String CANT_SAVE_TO_PERSONAL_TITLE = "DocumentsUi.CANT_SAVE_TO_PERSONAL_TITLE";
- field public static final String CANT_SAVE_TO_WORK_MESSAGE = "DocumentsUi.CANT_SAVE_TO_WORK_MESSAGE";
- field public static final String CANT_SAVE_TO_WORK_TITLE = "DocumentsUi.CANT_SAVE_TO_WORK_TITLE";
- field public static final String CANT_SELECT_PERSONAL_FILES_MESSAGE = "DocumentsUi.CANT_SELECT_PERSONAL_FILES_MESSAGE";
- field public static final String CANT_SELECT_PERSONAL_FILES_TITLE = "DocumentsUi.CANT_SELECT_PERSONAL_FILES_TITLE";
- field public static final String CANT_SELECT_WORK_FILES_MESSAGE = "DocumentsUi.CANT_SELECT_WORK_FILES_MESSAGE";
- field public static final String CANT_SELECT_WORK_FILES_TITLE = "DocumentsUi.CANT_SELECT_WORK_FILES_TITLE";
- field public static final String CROSS_PROFILE_NOT_ALLOWED_MESSAGE = "DocumentsUi.CROSS_PROFILE_NOT_ALLOWED_MESSAGE";
- field public static final String CROSS_PROFILE_NOT_ALLOWED_TITLE = "DocumentsUi.CROSS_PROFILE_NOT_ALLOWED_TITLE";
- field public static final String PERSONAL_TAB = "DocumentsUi.PERSONAL_TAB";
- field public static final String PREVIEW_WORK_FILE_ACCESSIBILITY = "DocumentsUi.PREVIEW_WORK_FILE_ACCESSIBILITY";
- field public static final String WORK_ACCESSIBILITY = "DocumentsUi.WORK_ACCESSIBILITY";
- field public static final String WORK_PROFILE_OFF_ENABLE_BUTTON = "DocumentsUi.WORK_PROFILE_OFF_ENABLE_BUTTON";
- field public static final String WORK_PROFILE_OFF_ERROR_TITLE = "DocumentsUi.WORK_PROFILE_OFF_ERROR_TITLE";
- field public static final String WORK_TAB = "DocumentsUi.WORK_TAB";
- }
-
- public static final class DevicePolicyResources.Strings.MediaProvider {
- field public static final String BLOCKED_BY_ADMIN_TITLE = "MediaProvider.BLOCKED_BY_ADMIN_TITLE";
- field public static final String BLOCKED_FROM_PERSONAL_MESSAGE = "MediaProvider.BLOCKED_FROM_PERSONAL_MESSAGE";
- field public static final String BLOCKED_FROM_WORK_MESSAGE = "MediaProvider.BLOCKED_FROM_WORK_MESSAGE";
- field public static final String SWITCH_TO_PERSONAL_MESSAGE = "MediaProvider.SWITCH_TO_PERSONAL_MESSAGE";
- field public static final String SWITCH_TO_WORK_MESSAGE = "MediaProvider.SWITCH_TO_WORK_MESSAGE";
- field public static final String WORK_PROFILE_PAUSED_MESSAGE = "MediaProvider.WORK_PROFILE_PAUSED_MESSAGE";
- field public static final String WORK_PROFILE_PAUSED_TITLE = "MediaProvider.WORK_PROFILE_PAUSED_TITLE";
}
public static final class DevicePolicyResources.Strings.PermissionController {
@@ -1237,6 +1200,13 @@
field public static final String WORK_PROFILE_DEFAULT_APPS_TITLE = "PermissionController.WORK_PROFILE_DEFAULT_APPS_TITLE";
}
+ public class DevicePolicyResourcesManager {
+ method @RequiresPermission(android.Manifest.permission.UPDATE_DEVICE_MANAGEMENT_RESOURCES) public void resetDrawables(@NonNull java.util.Set<java.lang.String>);
+ method @RequiresPermission(android.Manifest.permission.UPDATE_DEVICE_MANAGEMENT_RESOURCES) public void resetStrings(@NonNull java.util.Set<java.lang.String>);
+ method @RequiresPermission(android.Manifest.permission.UPDATE_DEVICE_MANAGEMENT_RESOURCES) public void setDrawables(@NonNull java.util.Set<android.app.admin.DevicePolicyDrawableResource>);
+ method @RequiresPermission(android.Manifest.permission.UPDATE_DEVICE_MANAGEMENT_RESOURCES) public void setStrings(@NonNull java.util.Set<android.app.admin.DevicePolicyStringResource>);
+ }
+
public final class DevicePolicyStringResource implements android.os.Parcelable {
ctor public DevicePolicyStringResource(@NonNull android.content.Context, @NonNull String, @StringRes int);
method public int describeContents();
@@ -1925,6 +1895,7 @@
field public static final int ACTION_DISMISS = 2; // 0x2
field public static final int ACTION_LAUNCH = 1; // 0x1
field public static final int ACTION_PIN = 3; // 0x3
+ field public static final int ACTION_UNDISMISS = 5; // 0x5
field public static final int ACTION_UNPIN = 4; // 0x4
field @NonNull public static final android.os.Parcelable.Creator<android.app.prediction.AppTargetEvent> CREATOR;
}
@@ -2620,13 +2591,13 @@
}
public final class UsageStatsManager {
- method @RequiresPermission(android.Manifest.permission.PACKAGE_USAGE_STATS) public void clearBroadcastResponseStats(@Nullable String, @IntRange(from=0) long);
+ method @RequiresPermission(android.Manifest.permission.ACCESS_BROADCAST_RESPONSE_STATS) public void clearBroadcastResponseStats(@Nullable String, @IntRange(from=0) long);
method @RequiresPermission(android.Manifest.permission.PACKAGE_USAGE_STATS) public int getAppStandbyBucket(String);
method @RequiresPermission(android.Manifest.permission.PACKAGE_USAGE_STATS) public java.util.Map<java.lang.String,java.lang.Integer> getAppStandbyBuckets();
method @RequiresPermission(allOf={android.Manifest.permission.INTERACT_ACROSS_USERS, android.Manifest.permission.PACKAGE_USAGE_STATS}) public long getLastTimeAnyComponentUsed(@NonNull String);
method public int getUsageSource();
method @RequiresPermission(android.Manifest.permission.BIND_CARRIER_SERVICES) public void onCarrierPrivilegedAppsChanged();
- method @NonNull @RequiresPermission(android.Manifest.permission.PACKAGE_USAGE_STATS) public java.util.List<android.app.usage.BroadcastResponseStats> queryBroadcastResponseStats(@Nullable String, @IntRange(from=0) long);
+ method @NonNull @RequiresPermission(android.Manifest.permission.ACCESS_BROADCAST_RESPONSE_STATS) public java.util.List<android.app.usage.BroadcastResponseStats> queryBroadcastResponseStats(@Nullable String, @IntRange(from=0) long);
method @RequiresPermission(allOf={android.Manifest.permission.SUSPEND_APPS, android.Manifest.permission.OBSERVE_APP_USAGE}) public void registerAppUsageLimitObserver(int, @NonNull String[], @NonNull java.time.Duration, @NonNull java.time.Duration, @Nullable android.app.PendingIntent);
method @RequiresPermission(android.Manifest.permission.OBSERVE_APP_USAGE) public void registerAppUsageObserver(int, @NonNull String[], long, @NonNull java.util.concurrent.TimeUnit, @NonNull android.app.PendingIntent);
method @RequiresPermission(android.Manifest.permission.OBSERVE_APP_USAGE) public void registerUsageSessionObserver(int, @NonNull String[], @NonNull java.time.Duration, @NonNull java.time.Duration, @NonNull android.app.PendingIntent, @Nullable android.app.PendingIntent);
@@ -3192,6 +3163,7 @@
}
public class CrossProfileApps {
+ method @RequiresPermission(anyOf={android.Manifest.permission.INTERACT_ACROSS_PROFILES, android.Manifest.permission.START_CROSS_PROFILE_ACTIVITIES}) public void startActivity(@NonNull android.content.ComponentName, @NonNull android.os.UserHandle, @Nullable android.app.Activity, @Nullable android.os.Bundle);
method @RequiresPermission(anyOf={android.Manifest.permission.INTERACT_ACROSS_PROFILES, android.Manifest.permission.START_CROSS_PROFILE_ACTIVITIES}) public void startActivity(@NonNull android.content.ComponentName, @NonNull android.os.UserHandle);
}
@@ -3411,6 +3383,8 @@
field public static final String EXTRA_REQUEST_PERMISSIONS_RESULTS = "android.content.pm.extra.REQUEST_PERMISSIONS_RESULTS";
field public static final String FEATURE_BROADCAST_RADIO = "android.hardware.broadcastradio";
field public static final String FEATURE_CONTEXT_HUB = "android.hardware.context_hub";
+ field public static final String FEATURE_EROFS = "android.software.erofs";
+ field public static final String FEATURE_EROFS_LEGACY = "android.software.erofs_legacy";
field public static final String FEATURE_GAME_SERVICE = "android.software.game_service";
field public static final String FEATURE_INCREMENTAL_DELIVERY = "android.software.incremental_delivery";
field public static final String FEATURE_REBOOT_ESCROW = "android.hardware.reboot_escrow";
@@ -5488,6 +5462,32 @@
method @NonNull public android.location.GnssCapabilities.Builder setHasSatellitePvt(boolean);
}
+ public final class GnssExcessPathInfo implements android.os.Parcelable {
+ method public int describeContents();
+ method @FloatRange(from=0.0f) public float getAttenuationDb();
+ method @FloatRange(from=0.0f) public float getExcessPathLengthMeters();
+ method @FloatRange(from=0.0f) public float getExcessPathLengthUncertaintyMeters();
+ method @NonNull public android.location.GnssReflectingPlane getReflectingPlane();
+ method public boolean hasAttenuation();
+ method public boolean hasExcessPathLength();
+ method public boolean hasExcessPathLengthUncertainty();
+ method public boolean hasReflectingPlane();
+ method public void writeToParcel(@NonNull android.os.Parcel, int);
+ field @NonNull public static final android.os.Parcelable.Creator<android.location.GnssExcessPathInfo> CREATOR;
+ }
+
+ public static final class GnssExcessPathInfo.Builder {
+ ctor public GnssExcessPathInfo.Builder();
+ method @NonNull public android.location.GnssExcessPathInfo build();
+ method @NonNull public android.location.GnssExcessPathInfo.Builder clearAttenuationDb();
+ method @NonNull public android.location.GnssExcessPathInfo.Builder clearExcessPathLengthMeters();
+ method @NonNull public android.location.GnssExcessPathInfo.Builder clearExcessPathLengthUncertaintyMeters();
+ method @NonNull public android.location.GnssExcessPathInfo.Builder setAttenuationDb(@FloatRange(from=0.0f) float);
+ method @NonNull public android.location.GnssExcessPathInfo.Builder setExcessPathLengthMeters(@FloatRange(from=0.0f) float);
+ method @NonNull public android.location.GnssExcessPathInfo.Builder setExcessPathLengthUncertaintyMeters(@FloatRange(from=0.0f) float);
+ method @NonNull public android.location.GnssExcessPathInfo.Builder setReflectingPlane(@Nullable android.location.GnssReflectingPlane);
+ }
+
public final class GnssMeasurement implements android.os.Parcelable {
method @Nullable public java.util.Collection<android.location.CorrelationVector> getCorrelationVectors();
method @Nullable public android.location.SatellitePvt getSatellitePvt();
@@ -5569,15 +5569,18 @@
public final class GnssSingleSatCorrection implements android.os.Parcelable {
method public int describeContents();
method @FloatRange(from=0.0f, fromInclusive=false) public float getCarrierFrequencyHz();
+ method @FloatRange(from=0.0f) public float getCombinedAttenuationDb();
method public int getConstellationType();
method @FloatRange(from=0.0f) public float getExcessPathLengthMeters();
method @FloatRange(from=0.0f) public float getExcessPathLengthUncertaintyMeters();
+ method @NonNull public java.util.List<android.location.GnssExcessPathInfo> getGnssExcessPathInfoList();
method @FloatRange(from=0.0f, to=1.0f) public float getProbabilityLineOfSight();
- method @Nullable public android.location.GnssReflectingPlane getReflectingPlane();
+ method @Deprecated @Nullable public android.location.GnssReflectingPlane getReflectingPlane();
method @IntRange(from=0) public int getSatelliteId();
+ method public boolean hasCombinedAttenuation();
method public boolean hasExcessPathLength();
method public boolean hasExcessPathLengthUncertainty();
- method public boolean hasReflectingPlane();
+ method @Deprecated public boolean hasReflectingPlane();
method public boolean hasValidSatelliteLineOfSight();
method public void writeToParcel(@NonNull android.os.Parcel, int);
field public static final android.os.Parcelable.Creator<android.location.GnssSingleSatCorrection> CREATOR;
@@ -5586,15 +5589,18 @@
public static final class GnssSingleSatCorrection.Builder {
ctor public GnssSingleSatCorrection.Builder();
method @NonNull public android.location.GnssSingleSatCorrection build();
+ method @NonNull public android.location.GnssSingleSatCorrection.Builder clearCombinedAttenuationDb();
method @NonNull public android.location.GnssSingleSatCorrection.Builder clearExcessPathLengthMeters();
method @NonNull public android.location.GnssSingleSatCorrection.Builder clearExcessPathLengthUncertaintyMeters();
method @NonNull public android.location.GnssSingleSatCorrection.Builder clearProbabilityLineOfSight();
method @NonNull public android.location.GnssSingleSatCorrection.Builder setCarrierFrequencyHz(@FloatRange(from=0.0f, fromInclusive=false) float);
+ method @NonNull public android.location.GnssSingleSatCorrection.Builder setCombinedAttenuationDb(@FloatRange(from=0.0f) float);
method @NonNull public android.location.GnssSingleSatCorrection.Builder setConstellationType(int);
method @NonNull public android.location.GnssSingleSatCorrection.Builder setExcessPathLengthMeters(@FloatRange(from=0.0f) float);
method @NonNull public android.location.GnssSingleSatCorrection.Builder setExcessPathLengthUncertaintyMeters(@FloatRange(from=0.0f) float);
+ method @NonNull public android.location.GnssSingleSatCorrection.Builder setGnssExcessPathInfoList(@NonNull java.util.List<android.location.GnssExcessPathInfo>);
method @NonNull public android.location.GnssSingleSatCorrection.Builder setProbabilityLineOfSight(@FloatRange(from=0.0f, to=1.0f) float);
- method @NonNull public android.location.GnssSingleSatCorrection.Builder setReflectingPlane(@Nullable android.location.GnssReflectingPlane);
+ method @Deprecated @NonNull public android.location.GnssSingleSatCorrection.Builder setReflectingPlane(@Nullable android.location.GnssReflectingPlane);
method @NonNull public android.location.GnssSingleSatCorrection.Builder setSatelliteId(@IntRange(from=0) int);
}
@@ -5836,9 +5842,9 @@
ctor public LastLocationRequest.Builder();
ctor public LastLocationRequest.Builder(@NonNull android.location.LastLocationRequest);
method @NonNull public android.location.LastLocationRequest build();
- method @NonNull @RequiresPermission(anyOf={android.Manifest.permission.WRITE_SECURE_SETTINGS, android.Manifest.permission.LOCATION_BYPASS}) public android.location.LastLocationRequest.Builder setAdasGnssBypass(boolean);
+ method @NonNull @RequiresPermission(android.Manifest.permission.LOCATION_BYPASS) public android.location.LastLocationRequest.Builder setAdasGnssBypass(boolean);
method @NonNull @RequiresPermission(android.Manifest.permission.UPDATE_APP_OPS_STATS) public android.location.LastLocationRequest.Builder setHiddenFromAppOps(boolean);
- method @NonNull @RequiresPermission(anyOf={android.Manifest.permission.WRITE_SECURE_SETTINGS, android.Manifest.permission.LOCATION_BYPASS}) public android.location.LastLocationRequest.Builder setLocationSettingsIgnored(boolean);
+ method @NonNull @RequiresPermission(android.Manifest.permission.LOCATION_BYPASS) public android.location.LastLocationRequest.Builder setLocationSettingsIgnored(boolean);
}
public class Location implements android.os.Parcelable {
@@ -5867,7 +5873,7 @@
method @Deprecated @RequiresPermission(anyOf={android.Manifest.permission.ACCESS_COARSE_LOCATION, android.Manifest.permission.ACCESS_FINE_LOCATION}) public void requestLocationUpdates(@Nullable android.location.LocationRequest, @NonNull android.location.LocationListener, @Nullable android.os.Looper);
method @Deprecated @RequiresPermission(anyOf={android.Manifest.permission.ACCESS_COARSE_LOCATION, android.Manifest.permission.ACCESS_FINE_LOCATION}) public void requestLocationUpdates(@Nullable android.location.LocationRequest, @NonNull java.util.concurrent.Executor, @NonNull android.location.LocationListener);
method @Deprecated @RequiresPermission(anyOf={android.Manifest.permission.ACCESS_COARSE_LOCATION, android.Manifest.permission.ACCESS_FINE_LOCATION}) public void requestLocationUpdates(@Nullable android.location.LocationRequest, @NonNull android.app.PendingIntent);
- method @RequiresPermission(anyOf={android.Manifest.permission.WRITE_SECURE_SETTINGS, android.Manifest.permission.LOCATION_BYPASS}) public void setAdasGnssLocationEnabled(boolean);
+ method @RequiresPermission(android.Manifest.permission.LOCATION_BYPASS) public void setAdasGnssLocationEnabled(boolean);
method @RequiresPermission(android.Manifest.permission.LOCATION_HARDWARE) public void setExtraLocationControllerPackage(@Nullable String);
method @RequiresPermission(android.Manifest.permission.LOCATION_HARDWARE) public void setExtraLocationControllerPackageEnabled(boolean);
method @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS) public void setLocationEnabledForUser(boolean, @NonNull android.os.UserHandle);
@@ -5900,7 +5906,7 @@
method @Deprecated @NonNull public android.location.LocationRequest setFastestInterval(long);
method @Deprecated public void setHideFromAppOps(boolean);
method @Deprecated @NonNull public android.location.LocationRequest setInterval(long);
- method @Deprecated @NonNull @RequiresPermission(anyOf={android.Manifest.permission.WRITE_SECURE_SETTINGS, android.Manifest.permission.LOCATION_BYPASS}) public android.location.LocationRequest setLocationSettingsIgnored(boolean);
+ method @Deprecated @NonNull @RequiresPermission(android.Manifest.permission.LOCATION_BYPASS) public android.location.LocationRequest setLocationSettingsIgnored(boolean);
method @Deprecated @NonNull public android.location.LocationRequest setLowPowerMode(boolean);
method @Deprecated @NonNull public android.location.LocationRequest setNumUpdates(int);
method @Deprecated @NonNull public android.location.LocationRequest setProvider(@NonNull String);
@@ -5916,9 +5922,9 @@
}
public static final class LocationRequest.Builder {
- method @NonNull @RequiresPermission(anyOf={android.Manifest.permission.WRITE_SECURE_SETTINGS, android.Manifest.permission.LOCATION_BYPASS}) public android.location.LocationRequest.Builder setAdasGnssBypass(boolean);
+ method @NonNull @RequiresPermission(android.Manifest.permission.LOCATION_BYPASS) public android.location.LocationRequest.Builder setAdasGnssBypass(boolean);
method @NonNull @RequiresPermission(android.Manifest.permission.UPDATE_APP_OPS_STATS) public android.location.LocationRequest.Builder setHiddenFromAppOps(boolean);
- method @NonNull @RequiresPermission(anyOf={android.Manifest.permission.WRITE_SECURE_SETTINGS, android.Manifest.permission.LOCATION_BYPASS}) public android.location.LocationRequest.Builder setLocationSettingsIgnored(boolean);
+ method @NonNull @RequiresPermission(android.Manifest.permission.LOCATION_BYPASS) public android.location.LocationRequest.Builder setLocationSettingsIgnored(boolean);
method @NonNull @RequiresPermission(android.Manifest.permission.LOCATION_HARDWARE) public android.location.LocationRequest.Builder setLowPower(boolean);
method @NonNull @RequiresPermission(android.Manifest.permission.UPDATE_DEVICE_STATS) public android.location.LocationRequest.Builder setWorkSource(@Nullable android.os.WorkSource);
}
@@ -9791,6 +9797,7 @@
method @RequiresPermission(anyOf={android.Manifest.permission.MANAGE_USERS, android.Manifest.permission.QUERY_USERS, android.Manifest.permission.INTERACT_ACROSS_USERS}, conditional=true) public boolean isManagedProfile(int);
method @RequiresPermission(anyOf={android.Manifest.permission.MANAGE_USERS, android.Manifest.permission.INTERACT_ACROSS_USERS}, conditional=true) public boolean isMediaSharedWithParent();
method @RequiresPermission(anyOf={android.Manifest.permission.MANAGE_USERS, android.Manifest.permission.CREATE_USERS, android.Manifest.permission.QUERY_USERS}) public boolean isPrimaryUser();
+ method public static boolean isRemoveResultSuccessful(int);
method public boolean isRestrictedProfile();
method @RequiresPermission(anyOf={android.Manifest.permission.MANAGE_USERS, android.Manifest.permission.CREATE_USERS}, conditional=true) public boolean isRestrictedProfile(@NonNull android.os.UserHandle);
method @RequiresPermission(anyOf={android.Manifest.permission.MANAGE_USERS, android.Manifest.permission.QUERY_USERS}) public boolean isSameProfileGroup(@NonNull android.os.UserHandle, @NonNull android.os.UserHandle);
@@ -9808,7 +9815,10 @@
field public static final String DISALLOW_RUN_IN_BACKGROUND = "no_run_in_background";
field public static final int REMOVE_RESULT_ALREADY_BEING_REMOVED = 2; // 0x2
field public static final int REMOVE_RESULT_DEFERRED = 1; // 0x1
- field public static final int REMOVE_RESULT_ERROR = 3; // 0x3
+ field public static final int REMOVE_RESULT_ERROR_SYSTEM_USER = -4; // 0xfffffffc
+ field public static final int REMOVE_RESULT_ERROR_UNKNOWN = -1; // 0xffffffff
+ field public static final int REMOVE_RESULT_ERROR_USER_NOT_FOUND = -3; // 0xfffffffd
+ field public static final int REMOVE_RESULT_ERROR_USER_RESTRICTION = -2; // 0xfffffffe
field public static final int REMOVE_RESULT_REMOVED = 0; // 0x0
field public static final int RESTRICTION_NOT_SET = 0; // 0x0
field public static final int RESTRICTION_SOURCE_DEVICE_OWNER = 2; // 0x2
@@ -10043,9 +10053,9 @@
method @BinderThread public void onOneTimePermissionSessionTimeout(@NonNull String);
method @Deprecated @BinderThread public void onRestoreDelayedRuntimePermissionsBackup(@NonNull String, @NonNull android.os.UserHandle, @NonNull java.util.function.Consumer<java.lang.Boolean>);
method @Deprecated @BinderThread public void onRestoreRuntimePermissionsBackup(@NonNull android.os.UserHandle, @NonNull java.io.InputStream, @NonNull Runnable);
- method @BinderThread public void onRevokeOwnPermissionsOnKill(@NonNull String, @NonNull java.util.List<java.lang.String>, @NonNull Runnable);
method @BinderThread public abstract void onRevokeRuntimePermission(@NonNull String, @NonNull String, @NonNull Runnable);
method @BinderThread public abstract void onRevokeRuntimePermissions(@NonNull java.util.Map<java.lang.String,java.util.List<java.lang.String>>, boolean, int, @NonNull String, @NonNull java.util.function.Consumer<java.util.Map<java.lang.String,java.util.List<java.lang.String>>>);
+ method @BinderThread public void onRevokeSelfPermissionsOnKill(@NonNull String, @NonNull java.util.List<java.lang.String>, @NonNull Runnable);
method @Deprecated @BinderThread public abstract void onSetRuntimePermissionGrantStateByDeviceAdmin(@NonNull String, @NonNull String, @NonNull String, int, @NonNull java.util.function.Consumer<java.lang.Boolean>);
method @BinderThread public void onSetRuntimePermissionGrantStateByDeviceAdmin(@NonNull String, @NonNull android.permission.AdminPermissionControlParams, @NonNull java.util.function.Consumer<java.lang.Boolean>);
method @BinderThread public void onStageAndApplyRuntimePermissionsBackup(@NonNull android.os.UserHandle, @NonNull java.io.InputStream, @NonNull Runnable);
@@ -10859,10 +10869,11 @@
}
public static final class AmbientContextDetectionResult.Builder {
- ctor public AmbientContextDetectionResult.Builder();
+ ctor public AmbientContextDetectionResult.Builder(@NonNull String);
method @NonNull public android.service.ambientcontext.AmbientContextDetectionResult.Builder addEvent(@NonNull android.app.ambientcontext.AmbientContextEvent);
+ method @NonNull public android.service.ambientcontext.AmbientContextDetectionResult.Builder addEvents(@NonNull java.util.List<android.app.ambientcontext.AmbientContextEvent>);
method @NonNull public android.service.ambientcontext.AmbientContextDetectionResult build();
- method @NonNull public android.service.ambientcontext.AmbientContextDetectionResult.Builder setPackageName(@NonNull String);
+ method @NonNull public android.service.ambientcontext.AmbientContextDetectionResult.Builder clearEvents();
}
public abstract class AmbientContextDetectionService extends android.app.Service {
@@ -10883,9 +10894,8 @@
}
public static final class AmbientContextDetectionServiceStatus.Builder {
- ctor public AmbientContextDetectionServiceStatus.Builder();
+ ctor public AmbientContextDetectionServiceStatus.Builder(@NonNull String);
method @NonNull public android.service.ambientcontext.AmbientContextDetectionServiceStatus build();
- method @NonNull public android.service.ambientcontext.AmbientContextDetectionServiceStatus.Builder setPackageName(@NonNull String);
method @NonNull public android.service.ambientcontext.AmbientContextDetectionServiceStatus.Builder setStatusCode(int);
}
@@ -11367,7 +11377,7 @@
method @RequiresPermission(android.Manifest.permission.MANAGE_GAME_ACTIVITY) public final boolean restartGame();
method public void setTaskOverlayView(@NonNull android.view.View, @NonNull android.view.ViewGroup.LayoutParams);
method @RequiresPermission(android.Manifest.permission.MANAGE_GAME_ACTIVITY) public final void startActivityFromGameSessionForResult(@NonNull android.content.Intent, @Nullable android.os.Bundle, @NonNull java.util.concurrent.Executor, @NonNull android.service.games.GameSessionActivityCallback);
- method public void takeScreenshot(@NonNull java.util.concurrent.Executor, @NonNull android.service.games.GameSession.ScreenshotCallback);
+ method @RequiresPermission(android.Manifest.permission.MANAGE_GAME_ACTIVITY) public void takeScreenshot(@NonNull java.util.concurrent.Executor, @NonNull android.service.games.GameSession.ScreenshotCallback);
}
public static interface GameSession.ScreenshotCallback {
diff --git a/core/api/test-current.txt b/core/api/test-current.txt
index 66f893d..a67d002 100644
--- a/core/api/test-current.txt
+++ b/core/api/test-current.txt
@@ -96,7 +96,7 @@
package android.animation {
public class ValueAnimator extends android.animation.Animator {
- method @MainThread public static void setDurationScale(@FloatRange(from=0, to=1) float);
+ method @MainThread public static void setDurationScale(@FloatRange(from=0) float);
}
}
@@ -300,7 +300,6 @@
}
public class LocaleManager {
- method @Nullable public android.os.LocaleList getSystemLocales();
method public void setSystemLocales(@NonNull android.os.LocaleList);
}
@@ -356,14 +355,8 @@
}
public final class PictureInPictureParams implements android.os.Parcelable {
- method public java.util.List<android.app.RemoteAction> getActions();
- method public float getAspectRatio();
- method @Nullable public android.app.RemoteAction getCloseAction();
- method public float getExpandedAspectRatio();
- method public android.graphics.Rect getSourceRectHint();
- method @Nullable public CharSequence getSubtitle();
- method @Nullable public CharSequence getTitle();
- method public boolean isSeamlessResizeEnabled();
+ method public float getAspectRatioFloat();
+ method public float getExpandedAspectRatioFloat();
}
public final class PictureInPictureUiState implements android.os.Parcelable {
@@ -508,6 +501,7 @@
method public void forceUpdateUserSetupComplete(int);
method @NonNull public java.util.Set<java.lang.String> getDefaultCrossProfilePackages();
method public int getDeviceOwnerType(@NonNull android.content.ComponentName);
+ method @Nullable public String getDevicePolicyManagementRoleHolderUpdaterPackage();
method @NonNull public java.util.Set<java.lang.String> getDisallowedSystemApps(@NonNull android.content.ComponentName, int, @NonNull String);
method public long getLastBugReportRequestTime();
method public long getLastNetworkLogRetrievalTime();
@@ -518,7 +512,6 @@
method public boolean isFactoryResetProtectionPolicySupported();
method @RequiresPermission(anyOf={android.Manifest.permission.MANAGE_USERS, android.Manifest.permission.INTERACT_ACROSS_USERS}) public boolean isNewUserDisclaimerAcknowledged();
method public boolean isRemovingAdmin(@NonNull android.content.ComponentName, int);
- method @RequiresPermission(anyOf={android.Manifest.permission.MARK_DEVICE_ORGANIZATION_OWNED, android.Manifest.permission.MANAGE_PROFILE_AND_DEVICE_OWNERS}, conditional=true) public void markProfileOwnerOnOrganizationOwnedDevice(@NonNull android.content.ComponentName);
method @NonNull public static String operationSafetyReasonToString(int);
method @NonNull public static String operationToString(int);
method @RequiresPermission(android.Manifest.permission.MANAGE_PROFILE_AND_DEVICE_OWNERS) public void resetDefaultCrossProfileIntentFilters(int);
@@ -527,6 +520,7 @@
method @RequiresPermission(android.Manifest.permission.MANAGE_PROFILE_AND_DEVICE_OWNERS) public boolean setDeviceOwnerOnly(@NonNull android.content.ComponentName, @Nullable String, int);
method public void setDeviceOwnerType(@NonNull android.content.ComponentName, int);
method @RequiresPermission(android.Manifest.permission.MANAGE_DEVICE_ADMINS) public void setNextOperationSafety(int, int);
+ method @RequiresPermission(anyOf={android.Manifest.permission.MARK_DEVICE_ORGANIZATION_OWNED, android.Manifest.permission.MANAGE_PROFILE_AND_DEVICE_OWNERS}, conditional=true) public void setProfileOwnerOnOrganizationOwnedDevice(@NonNull android.content.ComponentName, boolean);
field public static final String ACTION_DATA_SHARING_RESTRICTION_APPLIED = "android.app.action.DATA_SHARING_RESTRICTION_APPLIED";
field public static final String ACTION_DEVICE_POLICY_CONSTANTS_CHANGED = "android.app.action.DEVICE_POLICY_CONSTANTS_CHANGED";
field public static final int DEVICE_OWNER_TYPE_DEFAULT = 0; // 0x0
@@ -2435,7 +2429,7 @@
package android.service.voice {
public class AlwaysOnHotwordDetector implements android.service.voice.HotwordDetector {
- method @RequiresPermission(allOf={android.Manifest.permission.RECORD_AUDIO, android.Manifest.permission.CAPTURE_AUDIO_HOTWORD}) public void triggerHardwareRecognitionEventForTest(int, int, boolean, int, int, int, boolean, @NonNull android.media.AudioFormat, @Nullable byte[]);
+ method @RequiresPermission(allOf={android.Manifest.permission.RECORD_AUDIO, android.Manifest.permission.CAPTURE_AUDIO_HOTWORD}) public void triggerHardwareRecognitionEventForTest(int, int, boolean, int, int, int, boolean, @NonNull android.media.AudioFormat, @Nullable byte[], @NonNull java.util.List<android.hardware.soundtrigger.SoundTrigger.KeyphraseRecognitionExtra>);
}
public static final class AlwaysOnHotwordDetector.EventPayload.Builder {
diff --git a/core/java/Android.bp b/core/java/Android.bp
index a5526bc..f081a43 100644
--- a/core/java/Android.bp
+++ b/core/java/Android.bp
@@ -145,16 +145,16 @@
out: ["com/android/internal/util/FrameworkStatsLog.java"],
}
+// Library that provides functionality to log UiEvents in framework space.
+// If this functionality is needed outside the framework, the interfaces library
+// can be re-used and a local implementation is needed.
java_library {
name: "uieventloggerlib",
srcs: [
- "com/android/internal/logging/UiEvent.java",
- "com/android/internal/logging/UiEventLogger.java",
"com/android/internal/logging/UiEventLoggerImpl.java",
- "com/android/internal/logging/InstanceId.java",
- "com/android/internal/logging/InstanceIdSequence.java",
":statslog-framework-java-gen",
],
+ static_libs: ["modules-utils-uieventlogger-interface"],
}
filegroup {
diff --git a/core/java/android/accessibilityservice/AccessibilityShortcutInfo.java b/core/java/android/accessibilityservice/AccessibilityShortcutInfo.java
index 4e6cfb35..f53cfe4 100644
--- a/core/java/android/accessibilityservice/AccessibilityShortcutInfo.java
+++ b/core/java/android/accessibilityservice/AccessibilityShortcutInfo.java
@@ -169,10 +169,6 @@
mIntroResId = asAttributes.getResourceId(
com.android.internal.R.styleable.AccessibilityShortcutTarget_intro, 0);
asAttributes.recycle();
-
- if ((mDescriptionResId == 0 && mHtmlDescriptionRes == 0) || mSummaryResId == 0) {
- throw new XmlPullParserException("No description or summary in meta-data");
- }
} catch (PackageManager.NameNotFoundException e) {
throw new XmlPullParserException("Unable to create context for: "
+ mActivityInfo.packageName);
diff --git a/core/java/android/accessibilityservice/InputMethod.java b/core/java/android/accessibilityservice/InputMethod.java
index 36cfd0e..c0e5e84 100644
--- a/core/java/android/accessibilityservice/InputMethod.java
+++ b/core/java/android/accessibilityservice/InputMethod.java
@@ -67,6 +67,10 @@
private InputConnection mStartedInputConnection;
private EditorInfo mInputEditorInfo;
+ /**
+ * Creates a new InputMethod instance for the given <code>service</code>, so that the
+ * accessibility service can control editing.
+ */
public InputMethod(@NonNull AccessibilityService service) {
mService = service;
}
diff --git a/core/java/android/accounts/CantAddAccountActivity.java b/core/java/android/accounts/CantAddAccountActivity.java
index 107efc3..3fac1a0 100644
--- a/core/java/android/accounts/CantAddAccountActivity.java
+++ b/core/java/android/accounts/CantAddAccountActivity.java
@@ -39,7 +39,7 @@
setContentView(R.layout.app_not_authorized);
TextView view = findViewById(R.id.description);
- String text = getSystemService(DevicePolicyManager.class).getString(
+ String text = getSystemService(DevicePolicyManager.class).getResources().getString(
CANT_ADD_ACCOUNT_MESSAGE,
() -> getString(R.string.error_message_change_not_allowed));
view.setText(text);
diff --git a/core/java/android/accounts/ChooseTypeAndAccountActivity.java b/core/java/android/accounts/ChooseTypeAndAccountActivity.java
index 0d82ac9..f623295d 100644
--- a/core/java/android/accounts/ChooseTypeAndAccountActivity.java
+++ b/core/java/android/accounts/ChooseTypeAndAccountActivity.java
@@ -205,7 +205,7 @@
setContentView(R.layout.app_not_authorized);
TextView view = findViewById(R.id.description);
- String text = getSystemService(DevicePolicyManager.class).getString(
+ String text = getSystemService(DevicePolicyManager.class).getResources().getString(
CANT_ADD_ACCOUNT_MESSAGE,
() -> getString(R.string.error_message_change_not_allowed));
view.setText(text);
diff --git a/core/java/android/animation/ValueAnimator.java b/core/java/android/animation/ValueAnimator.java
index bca6b6a..6ab7ae6 100644
--- a/core/java/android/animation/ValueAnimator.java
+++ b/core/java/android/animation/ValueAnimator.java
@@ -316,7 +316,7 @@
@UnsupportedAppUsage
@TestApi
@MainThread
- public static void setDurationScale(@FloatRange(from = 0, to = 1) float durationScale) {
+ public static void setDurationScale(@FloatRange(from = 0) float durationScale) {
sDurationScale = durationScale;
List<WeakReference<DurationScaleChangeListener>> listenerCopy;
@@ -340,7 +340,7 @@
*
* @return the duration scale.
*/
- @FloatRange(from = 0, to = 1)
+ @FloatRange(from = 0)
public static float getDurationScale() {
return sDurationScale;
}
@@ -1798,8 +1798,8 @@
public interface DurationScaleChangeListener {
/**
* Called when the duration scale changes.
- * @param scale the duration scalel
+ * @param scale the duration scale
*/
- void onChanged(float scale);
+ void onChanged(@FloatRange(from = 0) float scale);
}
}
diff --git a/core/java/android/app/ActivityManager.java b/core/java/android/app/ActivityManager.java
index 9f15105..e8c903f 100644
--- a/core/java/android/app/ActivityManager.java
+++ b/core/java/android/app/ActivityManager.java
@@ -22,6 +22,7 @@
import static android.content.pm.ActivityInfo.RESIZE_MODE_RESIZEABLE;
import android.Manifest;
+import android.annotation.ColorInt;
import android.annotation.DrawableRes;
import android.annotation.IntDef;
import android.annotation.IntRange;
@@ -185,6 +186,11 @@
* @hide
*/
public static final int INSTR_FLAG_ALWAYS_CHECK_SIGNATURE = 1 << 4;
+ /**
+ * Instrument Sdk Sandbox process that corresponds to the target package.
+ * @hide
+ */
+ public static final int INSTR_FLAG_INSTRUMENT_SDK_SANDBOX = 1 << 5;
static final class UidObserver extends IUidObserver.Stub {
final OnUidImportanceListener mListener;
@@ -1264,6 +1270,104 @@
private int mMinWidth;
private int mMinHeight;
+ /**
+ * Provides a convenient way to set the fields of a {@link TaskDescription} when creating a
+ * new instance.
+ */
+ public static final class Builder {
+ /**
+ * Default values for the TaskDescription
+ */
+ @Nullable
+ private String mLabel = null;
+ @DrawableRes
+ private int mIconRes = Resources.ID_NULL;
+ private int mPrimaryColor = 0;
+ private int mBackgroundColor = 0;
+ private int mStatusBarColor = 0;
+ private int mNavigationBarColor = 0;
+
+ /**
+ * Set the label to use in the TaskDescription.
+ * @param label A label and description of the current state of this activity.
+ * @return The same instance of the builder.
+ */
+ @NonNull
+ public Builder setLabel(@Nullable String label) {
+ this.mLabel = label;
+ return this;
+ }
+
+ /**
+ * Set the drawable resource of the icon to use in the TaskDescription.
+ * @param iconRes A drawable resource of an icon that represents the current state of
+ * this activity.
+ * @return The same instance of the builder.
+ */
+ @NonNull
+ public Builder setIcon(@DrawableRes int iconRes) {
+ this.mIconRes = iconRes;
+ return this;
+ }
+
+ /**
+ * Set the primary color to use in the TaskDescription.
+ * @param color A color to override the theme's primary color. The color must be opaque.
+ * @return The same instance of the builder.
+ */
+ @NonNull
+ public Builder setPrimaryColor(@ColorInt int color) {
+ this.mPrimaryColor = color;
+ return this;
+ }
+
+ /**
+ * Set the background color to use in the TaskDescription.
+ * @param color A color to override the theme's background color. The color must be
+ * opaque.
+ * @return The same instance of the builder.
+ */
+ @NonNull
+ public Builder setBackgroundColor(@ColorInt int color) {
+ this.mBackgroundColor = color;
+ return this;
+ }
+
+ /**
+ * Set the status bar color to use in the TaskDescription.
+ * @param color A color to override the theme's status bar color.
+ * @return The same instance of the builder.
+ */
+ @NonNull
+ public Builder setStatusBarColor(@ColorInt int color) {
+ this.mStatusBarColor = color;
+ return this;
+ }
+
+ /**
+ * Set the navigation bar color to use in the TaskDescription.
+ * @param color A color to override the theme's navigation bar color.
+ * @return The same instance of the builder.
+ */
+ @NonNull
+ public Builder setNavigationBarColor(@ColorInt int color) {
+ this.mNavigationBarColor = color;
+ return this;
+ }
+
+ /**
+ * Build the TaskDescription.
+ * @return the TaskDescription object.
+ */
+ @NonNull
+ public TaskDescription build() {
+ final Icon icon = mIconRes == Resources.ID_NULL ? null :
+ Icon.createWithResource(ActivityThread.currentPackageName(), mIconRes);
+ return new TaskDescription(mLabel, icon, mPrimaryColor, mBackgroundColor,
+ mStatusBarColor, mNavigationBarColor, false, false, RESIZE_MODE_RESIZEABLE,
+ -1, -1, 0);
+ }
+ }
/**
* Creates the TaskDescription to the specified values.
@@ -1273,7 +1377,10 @@
* activity.
* @param colorPrimary A color to override the theme's primary color. This color must be
* opaque.
+ *
+ * @deprecated Use {@link Builder} instead.
*/
+ @Deprecated
public TaskDescription(String label, @DrawableRes int iconRes, int colorPrimary) {
this(label, Icon.createWithResource(ActivityThread.currentPackageName(), iconRes),
colorPrimary, 0, 0, 0, false, false, RESIZE_MODE_RESIZEABLE, -1, -1, 0);
@@ -1288,7 +1395,10 @@
* @param label A label and description of the current state of this activity.
* @param iconRes A drawable resource of an icon that represents the current state of this
* activity.
+ *
+ * @deprecated Use {@link Builder} instead.
*/
+ @Deprecated
public TaskDescription(String label, @DrawableRes int iconRes) {
this(label, Icon.createWithResource(ActivityThread.currentPackageName(), iconRes),
0, 0, 0, 0, false, false, RESIZE_MODE_RESIZEABLE, -1, -1, 0);
@@ -1298,14 +1408,20 @@
* Creates the TaskDescription to the specified values.
*
* @param label A label and description of the current state of this activity.
+ *
+ * @deprecated Use {@link Builder} instead.
*/
+ @Deprecated
public TaskDescription(String label) {
this(label, null, 0, 0, 0, 0, false, false, RESIZE_MODE_RESIZEABLE, -1, -1, 0);
}
/**
* Creates an empty TaskDescription.
+ *
+ * @deprecated Use {@link Builder} instead.
*/
+ @Deprecated
public TaskDescription() {
this(null, null, 0, 0, 0, 0, false, false, RESIZE_MODE_RESIZEABLE, -1, -1, 0);
}
@@ -1317,7 +1433,8 @@
* @param icon An icon that represents the current state of this task.
* @param colorPrimary A color to override the theme's primary color. This color must be
* opaque.
- * @deprecated use TaskDescription constructor with icon resource instead
+ *
+ * @deprecated Use {@link Builder} instead.
*/
@Deprecated
public TaskDescription(String label, Bitmap icon, int colorPrimary) {
@@ -1333,7 +1450,8 @@
*
* @param label A label and description of the current state of this activity.
* @param icon An icon that represents the current state of this activity.
- * @deprecated use TaskDescription constructor with icon resource instead
+ *
+ * @deprecated Use {@link Builder} instead.
*/
@Deprecated
public TaskDescription(String label, Bitmap icon) {
@@ -1635,15 +1753,15 @@
/**
* @return The color override on the theme's primary color.
*/
+ @ColorInt
public int getPrimaryColor() {
return mColorPrimary;
}
/**
- * @return The background color.
- * @hide
+ * @return The color override on the theme's background color.
*/
- @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
+ @ColorInt
public int getBackgroundColor() {
return mColorBackground;
}
@@ -1657,15 +1775,17 @@
}
/**
- * @hide
+ * @return The color override on the theme's status bar color.
*/
+ @ColorInt
public int getStatusBarColor() {
return mStatusBarColor;
}
/**
- * @hide
+ * @return The color override on the theme's navigation bar color.
*/
+ @ColorInt
public int getNavigationBarColor() {
return mNavigationBarColor;
}
diff --git a/core/java/android/app/ApplicationPackageManager.java b/core/java/android/app/ApplicationPackageManager.java
index 7ffa61b..d641a3b 100644
--- a/core/java/android/app/ApplicationPackageManager.java
+++ b/core/java/android/app/ApplicationPackageManager.java
@@ -18,9 +18,9 @@
import static android.app.admin.DevicePolicyResources.Drawables.Style.SOLID_COLORED;
import static android.app.admin.DevicePolicyResources.Drawables.Style.SOLID_NOT_COLORED;
-import static android.app.admin.DevicePolicyResources.Drawables.UNDEFINED;
import static android.app.admin.DevicePolicyResources.Drawables.WORK_PROFILE_ICON;
import static android.app.admin.DevicePolicyResources.Drawables.WORK_PROFILE_ICON_BADGE;
+import static android.app.admin.DevicePolicyResources.UNDEFINED;
import static android.content.pm.Checksum.TYPE_PARTIAL_MERKLE_ROOT_1M_SHA256;
import static android.content.pm.Checksum.TYPE_PARTIAL_MERKLE_ROOT_1M_SHA512;
import static android.content.pm.Checksum.TYPE_WHOLE_MD5;
@@ -1886,7 +1886,7 @@
return icon;
}
- final Drawable badgeForeground = getDevicePolicyManager().getDrawable(
+ final Drawable badgeForeground = getDevicePolicyManager().getResources().getDrawable(
getUpdatableUserIconBadgeId(user),
SOLID_COLORED,
() -> getDefaultUserIconBadge(user));
@@ -1938,11 +1938,12 @@
return null;
}
- final Drawable badgeForeground = getDevicePolicyManager().getDrawableForDensity(
- getUpdatableUserBadgeId(user),
- SOLID_COLORED,
- density,
- () -> getDefaultUserBadgeForDensity(user, density));
+ final Drawable badgeForeground = getDevicePolicyManager().getResources()
+ .getDrawableForDensity(
+ getUpdatableUserBadgeId(user),
+ SOLID_COLORED,
+ density,
+ () -> getDefaultUserBadgeForDensity(user, density));
badgeForeground.setTint(getUserBadgeColor(user, false));
Drawable badge = new LayerDrawable(new Drawable[] {badgeColor, badgeForeground });
@@ -1968,7 +1969,7 @@
return null;
}
- final Drawable badge = getDevicePolicyManager().getDrawableForDensity(
+ final Drawable badge = getDevicePolicyManager().getResources().getDrawableForDensity(
getUpdatableUserBadgeId(user),
SOLID_NOT_COLORED,
density,
diff --git a/core/java/android/app/ContextImpl.java b/core/java/android/app/ContextImpl.java
index f5eb1f6..ac46066 100644
--- a/core/java/android/app/ContextImpl.java
+++ b/core/java/android/app/ContextImpl.java
@@ -77,6 +77,7 @@
import android.os.UserHandle;
import android.os.UserManager;
import android.os.storage.StorageManager;
+import android.permission.PermissionControllerManager;
import android.permission.PermissionManager;
import android.system.ErrnoException;
import android.system.Os;
@@ -216,6 +217,12 @@
@UnsupportedAppUsage
private @Nullable ClassLoader mClassLoader;
+ /**
+ * The {@link com.android.server.wm.WindowToken} representing this instance if it is
+ * {@link #CONTEXT_TYPE_WINDOW_CONTEXT} or {@link #CONTEXT_TYPE_SYSTEM_OR_SYSTEM_UI}.
+ * If the type is {@link #CONTEXT_TYPE_ACTIVITY}, then represents the
+ * {@link android.window.WindowContainerToken} of the activity.
+ */
private final @Nullable IBinder mToken;
private final @NonNull UserHandle mUser;
@@ -2180,8 +2187,9 @@
}
@Override
- public void revokeOwnPermissionsOnKill(@NonNull Collection<String> permissions) {
- getSystemService(PermissionManager.class).revokeOwnPermissionsOnKill(permissions);
+ public void revokeSelfPermissionsOnKill(@NonNull Collection<String> permissions) {
+ getSystemService(PermissionControllerManager.class).revokeSelfPermissionsOnKill(
+ getPackageName(), new ArrayList<String>(permissions));
}
@Override
diff --git a/core/java/android/app/Dialog.java b/core/java/android/app/Dialog.java
index 82ff42b..a763b14 100644
--- a/core/java/android/app/Dialog.java
+++ b/core/java/android/app/Dialog.java
@@ -465,7 +465,8 @@
onBackPressed();
}
};
- getOnBackInvokedDispatcher().registerSystemOnBackInvokedCallback(mDefaultBackCallback);
+ getOnBackInvokedDispatcher().registerOnBackInvokedCallback(
+ OnBackInvokedDispatcher.PRIORITY_DEFAULT, mDefaultBackCallback);
mDefaultBackCallback = null;
}
}
diff --git a/core/java/android/app/GameManager.java b/core/java/android/app/GameManager.java
index 6f49c9e..a138fa1 100644
--- a/core/java/android/app/GameManager.java
+++ b/core/java/android/app/GameManager.java
@@ -191,7 +191,7 @@
*/
@TestApi
@RequiresPermission(Manifest.permission.MANAGE_GAME_MODE)
- public @GameMode boolean isAngleEnabled(@NonNull String packageName) {
+ public boolean isAngleEnabled(@NonNull String packageName) {
try {
return mService.isAngleEnabled(packageName, mContext.getUserId());
} catch (RemoteException e) {
diff --git a/core/java/android/app/ILocaleManager.aidl b/core/java/android/app/ILocaleManager.aidl
index 348cb2d..3002c8b 100644
--- a/core/java/android/app/ILocaleManager.aidl
+++ b/core/java/android/app/ILocaleManager.aidl
@@ -40,4 +40,9 @@
*/
LocaleList getApplicationLocales(String packageName, int userId);
+ /**
+ * Returns the current system locales.
+ */
+ LocaleList getSystemLocales();
+
}
\ No newline at end of file
diff --git a/core/java/android/app/Instrumentation.java b/core/java/android/app/Instrumentation.java
index e0c69df..ac979c4 100644
--- a/core/java/android/app/Instrumentation.java
+++ b/core/java/android/app/Instrumentation.java
@@ -393,6 +393,15 @@
}
/**
+ * Resets the {@link #setInTouchMode touch mode} to the device default.
+ */
+ public void resetInTouchMode() {
+ final boolean defaultInTouchMode = getContext().getResources().getBoolean(
+ com.android.internal.R.bool.config_defaultInTouchMode);
+ setInTouchMode(defaultInTouchMode);
+ }
+
+ /**
* Schedule a callback for when the application's main thread goes idle
* (has no more events to process).
*
diff --git a/core/java/android/app/KeyguardManager.java b/core/java/android/app/KeyguardManager.java
index cedf483e..e9c29b8 100644
--- a/core/java/android/app/KeyguardManager.java
+++ b/core/java/android/app/KeyguardManager.java
@@ -1103,9 +1103,12 @@
}
/**
- * Registers a listener to execute when the keyguard visibility changes.
+ * Registers a listener to execute when the keyguard locked state changes.
*
- * @param listener The listener to add to receive keyguard visibility changes.
+ * @param listener The listener to add to receive keyguard locked state changes.
+ *
+ * @see #isKeyguardLocked()
+ * @see #removeKeyguardLockedStateListener(KeyguardLockedStateListener)
*/
@RequiresPermission(Manifest.permission.SUBSCRIBE_TO_KEYGUARD_LOCKED_STATE)
public void addKeyguardLockedStateListener(@NonNull @CallbackExecutor Executor executor,
@@ -1124,7 +1127,12 @@
}
/**
- * Unregisters a listener that executes when the keyguard visibility changes.
+ * Unregisters a listener that executes when the keyguard locked state changes.
+ *
+ * @param listener The listener to remove.
+ *
+ * @see #isKeyguardLocked()
+ * @see #addKeyguardLockedStateListener(Executor, KeyguardLockedStateListener)
*/
@RequiresPermission(Manifest.permission.SUBSCRIBE_TO_KEYGUARD_LOCKED_STATE)
public void removeKeyguardLockedStateListener(@NonNull KeyguardLockedStateListener listener) {
diff --git a/core/java/android/app/LocaleManager.java b/core/java/android/app/LocaleManager.java
index 522dc84..efe9e35 100644
--- a/core/java/android/app/LocaleManager.java
+++ b/core/java/android/app/LocaleManager.java
@@ -18,7 +18,6 @@
import android.Manifest;
import android.annotation.NonNull;
-import android.annotation.Nullable;
import android.annotation.RequiresPermission;
import android.annotation.SystemApi;
import android.annotation.SystemService;
@@ -127,6 +126,26 @@
}
/**
+ * Returns the current system locales, ignoring app-specific overrides.
+ *
+ * <p><b>Note:</b> Apps should generally access the user's locale preferences as indicated in
+ * their in-process {@link LocaleList}s. However, in case an app-specific locale is set, this
+ * method helps cater to rare use-cases which might require specifically knowing the system
+ * locale.
+ *
+ * <p><b>Note:</b> This API is not user-aware. It returns the system locales for the foreground
+ * user.
+ */
+ @NonNull
+ public LocaleList getSystemLocales() {
+ try {
+ return mService.getSystemLocales();
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+
+ /**
* Sets the current system locales to the provided value.
*
* @hide
@@ -142,19 +161,4 @@
}
}
- /**
- * Returns the current system locales for the device.
- *
- * @hide
- */
- @TestApi
- @Nullable
- public LocaleList getSystemLocales() {
- try {
- return ActivityManager.getService().getConfiguration().getLocales();
- } catch (RemoteException e) {
- throw e.rethrowFromSystemServer();
- }
- }
-
}
diff --git a/core/java/android/app/Notification.java b/core/java/android/app/Notification.java
index 7e0cea89..6e1d1cd 100644
--- a/core/java/android/app/Notification.java
+++ b/core/java/android/app/Notification.java
@@ -19,8 +19,8 @@
import static android.annotation.Dimension.DP;
import static android.app.admin.DevicePolicyResources.Drawables.Source.NOTIFICATION;
import static android.app.admin.DevicePolicyResources.Drawables.Style.SOLID_COLORED;
-import static android.app.admin.DevicePolicyResources.Drawables.UNDEFINED;
import static android.app.admin.DevicePolicyResources.Drawables.WORK_PROFILE_ICON;
+import static android.app.admin.DevicePolicyResources.UNDEFINED;
import static android.graphics.drawable.Icon.TYPE_URI;
import static android.graphics.drawable.Icon.TYPE_URI_ADAPTIVE_BITMAP;
@@ -5079,7 +5079,7 @@
// Note: This assumes that the current user can read the profile badge of the
// originating user.
DevicePolicyManager dpm = mContext.getSystemService(DevicePolicyManager.class);
- return dpm.getDrawable(
+ return dpm.getResources().getDrawable(
getUpdatableProfileBadgeId(), SOLID_COLORED, NOTIFICATION,
this::getDefaultProfileBadgeDrawable);
}
diff --git a/core/java/android/app/PictureInPictureParams.java b/core/java/android/app/PictureInPictureParams.java
index 2d2788c..3f1844e 100644
--- a/core/java/android/app/PictureInPictureParams.java
+++ b/core/java/android/app/PictureInPictureParams.java
@@ -280,7 +280,7 @@
private Rational mAspectRatio;
/**
- * The expected aspect ratio of the vertically expanded picture-in-picture window.
+ * The expected aspect ratio of the expanded picture-in-picture window.
*/
@Nullable
private Rational mExpandedAspectRatio;
@@ -441,15 +441,21 @@
* @hide
*/
@TestApi
- public float getAspectRatio() {
+ public float getAspectRatioFloat() {
if (mAspectRatio != null) {
return mAspectRatio.floatValue();
}
return 0f;
}
- /** @hide */
- public Rational getAspectRatioRational() {
+ /**
+ * Returns the expected aspect ratio of the picture-in-picture window.
+ *
+ * @return aspect ratio as the desired width / height or {@code null} if not set.
+ * @see PictureInPictureParams.Builder#setAspectRatio(Rational)
+ */
+ @Nullable
+ public Rational getAspectRatio() {
return mAspectRatio;
}
@@ -466,7 +472,7 @@
* @hide
*/
@TestApi
- public float getExpandedAspectRatio() {
+ public float getExpandedAspectRatioFloat() {
if (mExpandedAspectRatio != null) {
return mExpandedAspectRatio.floatValue();
}
@@ -474,6 +480,17 @@
}
/**
+ * Returns the desired aspect ratio of the expanded picture-in-picture window.
+ *
+ * @return aspect ratio as the desired width / height or {@code null} if not set.
+ * @see PictureInPictureParams.Builder#setExpandedAspectRatio(Rational)
+ */
+ @Nullable
+ public Rational getExpandedAspectRatio() {
+ return mExpandedAspectRatio;
+ }
+
+ /**
* @return whether the expanded aspect ratio is set
* @hide
*/
@@ -482,11 +499,17 @@
}
/**
- * @return the set of user actions.
- * @hide
+ * Returns the list of user actions that are associated with the activity when in
+ * picture-in-picture mode.
+ *
+ * @return the user actions in a new list.
+ * @see PictureInPictureParams.Builder#setActions(List)
*/
- @TestApi
+ @NonNull
public List<RemoteAction> getActions() {
+ if (mUserActions == null) {
+ return new ArrayList<>();
+ }
return mUserActions;
}
@@ -499,10 +522,11 @@
}
/**
- * @return the close action.
- * @hide
+ * Returns the action that is to replace the system close action.
+ *
+ * @return the close action or {@code null} if not set.
+ * @see PictureInPictureParams.Builder#setCloseAction(RemoteAction)
*/
- @TestApi
@Nullable
public RemoteAction getCloseAction() {
return mCloseAction;
@@ -528,10 +552,12 @@
}
/**
- * @return the source rect hint
- * @hide
+ * Returns the source rect hint.
+ *
+ * @return the source rect hint also known as launch bounds or {@code null} if not set.
+ * @see PictureInPictureParams.Builder#setSourceRectHint(Rect)
*/
- @TestApi
+ @Nullable
public Rect getSourceRectHint() {
return mSourceRectHint;
}
@@ -545,18 +571,23 @@
}
/**
- * @return whether auto pip is enabled.
- * @hide
+ * Returns whether auto enter picture-in-picture is enabled.
+ *
+ * @return {@code true} if the system will automatically put the activity in
+ * picture-in-picture mode.
+ * @see PictureInPictureParams.Builder#setAutoEnterEnabled(boolean)
*/
public boolean isAutoEnterEnabled() {
return mAutoEnterEnabled == null ? false : mAutoEnterEnabled;
}
/**
- * @return whether seamless resize is enabled.
- * @hide
+ * Returns whether seamless resize is enabled.
+ *
+ * @return true if the system can seamlessly resize the window while activity is in
+ * picture-in-picture mode.
+ * @see PictureInPictureParams.Builder#setSeamlessResizeEnabled(boolean)
*/
- @TestApi
public boolean isSeamlessResizeEnabled() {
return mSeamlessResizeEnabled == null ? true : mSeamlessResizeEnabled;
}
@@ -570,10 +601,11 @@
}
/**
- * @return title of the pip.
- * @hide
+ * Returns the title of the picture-in-picture window that may be displayed to the user.
+ *
+ * @return title of the picture-in-picture window.
+ * @see PictureInPictureParams.Builder#setTitle(CharSequence)
*/
- @TestApi
@Nullable
public CharSequence getTitle() {
return mTitle;
@@ -588,10 +620,11 @@
}
/**
- * @return subtitle of the pip.
- * @hide
+ * Returns the subtitle of the picture-in-picture window that may be displayed to the user.
+ *
+ * @return subtitle of the picture-in-picture window.
+ * @see PictureInPictureParams.Builder#setSubtitle(CharSequence)
*/
- @TestApi
@Nullable
public CharSequence getSubtitle() {
return mSubtitle;
@@ -716,7 +749,7 @@
@Override
public String toString() {
return "PictureInPictureParams("
- + " aspectRatio=" + getAspectRatioRational()
+ + " aspectRatio=" + getAspectRatio()
+ " expandedAspectRatio=" + mExpandedAspectRatio
+ " sourceRectHint=" + getSourceRectHint()
+ " hasSetActions=" + hasSetActions()
diff --git a/core/java/android/app/StatusBarManager.java b/core/java/android/app/StatusBarManager.java
index 89854bb..ae0fc09 100644
--- a/core/java/android/app/StatusBarManager.java
+++ b/core/java/android/app/StatusBarManager.java
@@ -24,6 +24,9 @@
import android.annotation.SystemApi;
import android.annotation.SystemService;
import android.annotation.TestApi;
+import android.app.compat.CompatChanges;
+import android.compat.annotation.ChangeId;
+import android.compat.annotation.EnabledSince;
import android.compat.annotation.UnsupportedAppUsage;
import android.content.ComponentName;
import android.content.Context;
@@ -39,6 +42,7 @@
import android.os.IBinder;
import android.os.RemoteException;
import android.os.ServiceManager;
+import android.os.UserHandle;
import android.util.Pair;
import android.util.Slog;
import android.view.View;
@@ -520,6 +524,27 @@
private final Map<NearbyMediaDevicesProvider, NearbyMediaDevicesProviderWrapper>
nearbyMediaDevicesProviderMap = new HashMap<>();
+ /**
+ * Media controls based on {@link android.app.Notification.MediaStyle} notifications will have
+ * actions based on the media session's {@link android.media.session.PlaybackState}, rather than
+ * the notification's actions.
+ *
+ * These actions will be:
+ * - Play/Pause (depending on whether the current state is a playing state)
+ * - Previous (if declared), or a custom action if the slot is not reserved with
+ * {@code SESSION_EXTRAS_KEY_SLOT_RESERVATION_SKIP_TO_PREV}
+ * - Next (if declared), or a custom action if the slot is not reserved with
+ * {@code SESSION_EXTRAS_KEY_SLOT_RESERVATION_SKIP_TO_NEXT}
+ * - Custom action
+ * - Custom action
+ *
+ * @see androidx.media.utils.MediaConstants#SESSION_EXTRAS_KEY_SLOT_RESERVATION_SKIP_TO_PREV
+ * @see androidx.media.utils.MediaConstants#SESSION_EXTRAS_KEY_SLOT_RESERVATION_SKIP_TO_NEXT
+ */
+ @ChangeId
+ @EnabledSince(targetSdkVersion = Build.VERSION_CODES.TIRAMISU)
+ private static final long MEDIA_CONTROL_SESSION_ACTIONS = 203800354L;
+
@UnsupportedAppUsage
private Context mContext;
private IStatusBarService mService;
@@ -1127,6 +1152,21 @@
}
}
+ /**
+ * Checks whether the given package should use session-based actions for its media controls.
+ *
+ * @param packageName App posting media controls
+ * @param user Current user handle
+ * @return true if the app supports session actions
+ *
+ * @hide
+ */
+ @RequiresPermission(allOf = {android.Manifest.permission.READ_COMPAT_CHANGE_CONFIG,
+ android.Manifest.permission.LOG_COMPAT_CHANGE})
+ public static boolean useMediaSessionActionsForApp(String packageName, UserHandle user) {
+ return CompatChanges.isChangeEnabled(MEDIA_CONTROL_SESSION_ACTIONS, packageName, user);
+ }
+
/** @hide */
public static String windowStateToString(int state) {
if (state == WINDOW_STATE_HIDING) return "WINDOW_STATE_HIDING";
diff --git a/core/java/android/app/SystemServiceRegistry.java b/core/java/android/app/SystemServiceRegistry.java
index bf6f634..6615374 100644
--- a/core/java/android/app/SystemServiceRegistry.java
+++ b/core/java/android/app/SystemServiceRegistry.java
@@ -154,6 +154,7 @@
import android.net.wifi.WifiFrameworkInitializer;
import android.net.wifi.nl80211.WifiNl80211Manager;
import android.nfc.NfcManager;
+import android.ondevicepersonalization.OnDevicePersonalizationFrameworkInitializer;
import android.os.BatteryManager;
import android.os.BatteryStats;
import android.os.BatteryStatsManager;
@@ -1560,6 +1561,7 @@
SafetyCenterFrameworkInitializer.registerServiceWrappers();
ConnectivityFrameworkInitializerTiramisu.registerServiceWrappers();
NearbyFrameworkInitializer.registerServiceWrappers();
+ OnDevicePersonalizationFrameworkInitializer.registerServiceWrappers();
} finally {
// If any of the above code throws, we're in a pretty bad shape and the process
// will likely crash, but we'll reset it just in case there's an exception handler...
diff --git a/core/java/android/app/TEST_MAPPING b/core/java/android/app/TEST_MAPPING
index 32207af..649f904 100644
--- a/core/java/android/app/TEST_MAPPING
+++ b/core/java/android/app/TEST_MAPPING
@@ -146,15 +146,6 @@
}
],
"file_patterns": ["(/|^)ContextImpl.java"]
- },
- {
- "file_patterns": ["(/|^)LocaleManager.java"],
- "name": "CtsLocaleManagerTestCases",
- "options": [
- {
- "exclude-annotation": "androidx.test.filters.FlakyTest"
- }
- ]
}
],
"presubmit-large": [
@@ -182,6 +173,16 @@
{
"file_patterns": ["(/|^)ActivityThreadTest.java"],
"name": "FrameworksCoreTests"
+ },
+ // TODO(b/225192026): Move back to presubmit after b/225192026 is fixed
+ {
+ "file_patterns": ["(/|^)LocaleManager.java"],
+ "name": "CtsLocaleManagerTestCases",
+ "options": [
+ {
+ "exclude-annotation": "androidx.test.filters.FlakyTest"
+ }
+ ]
}
]
}
diff --git a/core/java/android/app/admin/DevicePolicyDrawableResource.java b/core/java/android/app/admin/DevicePolicyDrawableResource.java
index 7fd8e89..dab9888 100644
--- a/core/java/android/app/admin/DevicePolicyDrawableResource.java
+++ b/core/java/android/app/admin/DevicePolicyDrawableResource.java
@@ -20,7 +20,6 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.SystemApi;
-import android.app.admin.DevicePolicyResources.Drawables;
import android.content.Context;
import android.os.Parcel;
import android.os.Parcelable;
@@ -29,21 +28,21 @@
/**
* Used to pass in the required information for updating an enterprise drawable resource using
- * {@link DevicePolicyManager#setDrawables}.
+ * {@link DevicePolicyResourcesManager#setDrawables}.
*
* @hide
*/
@SystemApi
public final class DevicePolicyDrawableResource implements Parcelable {
- @NonNull private final @DevicePolicyResources.UpdatableDrawableId String mDrawableId;
- @NonNull private final @DevicePolicyResources.UpdatableDrawableStyle String mDrawableStyle;
- @NonNull private final @DevicePolicyResources.UpdatableDrawableSource String mDrawableSource;
+ @NonNull private final String mDrawableId;
+ @NonNull private final String mDrawableStyle;
+ @NonNull private final String mDrawableSource;
private final @DrawableRes int mResourceIdInCallingPackage;
@NonNull private ParcelableResource mResource;
/**
* Creates an object containing the required information for updating an enterprise drawable
- * resource using {@link DevicePolicyManager#setDrawables}.
+ * resource using {@link DevicePolicyResourcesManager#setDrawables}.
*
* <p>It will be used to update the drawable defined by {@code drawableId} with style
* {@code drawableStyle} located in source {@code drawableSource} to the drawable with ID
@@ -60,9 +59,9 @@
*/
public DevicePolicyDrawableResource(
@NonNull Context context,
- @NonNull @DevicePolicyResources.UpdatableDrawableId String drawableId,
- @NonNull @DevicePolicyResources.UpdatableDrawableStyle String drawableStyle,
- @NonNull @DevicePolicyResources.UpdatableDrawableSource String drawableSource,
+ @NonNull String drawableId,
+ @NonNull String drawableStyle,
+ @NonNull String drawableSource,
@DrawableRes int resourceIdInCallingPackage) {
this(drawableId, drawableStyle, drawableSource, resourceIdInCallingPackage,
new ParcelableResource(context, resourceIdInCallingPackage,
@@ -70,9 +69,9 @@
}
private DevicePolicyDrawableResource(
- @NonNull @DevicePolicyResources.UpdatableDrawableId String drawableId,
- @NonNull @DevicePolicyResources.UpdatableDrawableStyle String drawableStyle,
- @NonNull @DevicePolicyResources.UpdatableDrawableSource String drawableSource,
+ @NonNull String drawableId,
+ @NonNull String drawableStyle,
+ @NonNull String drawableSource,
@DrawableRes int resourceIdInCallingPackage,
@NonNull ParcelableResource resource) {
@@ -90,7 +89,7 @@
/**
* Creates an object containing the required information for updating an enterprise drawable
- * resource using {@link DevicePolicyManager#setDrawables}.
+ * resource using {@link DevicePolicyResourcesManager#setDrawables}.
* <p>It will be used to update the drawable defined by {@code drawableId} with style
* {@code drawableStyle} to the drawable with ID {@code resourceIdInCallingPackage} in the
* calling package</p>
@@ -105,10 +104,10 @@
*/
public DevicePolicyDrawableResource(
@NonNull Context context,
- @NonNull @DevicePolicyResources.UpdatableDrawableId String drawableId,
- @NonNull @DevicePolicyResources.UpdatableDrawableStyle String drawableStyle,
+ @NonNull String drawableId,
+ @NonNull String drawableStyle,
@DrawableRes int resourceIdInCallingPackage) {
- this(context, drawableId, drawableStyle, Drawables.Source.UNDEFINED,
+ this(context, drawableId, drawableStyle, DevicePolicyResources.UNDEFINED,
resourceIdInCallingPackage);
}
@@ -116,7 +115,6 @@
* Returns the ID of the drawable to update.
*/
@NonNull
- @DevicePolicyResources.UpdatableDrawableId
public String getDrawableId() {
return mDrawableId;
}
@@ -125,7 +123,6 @@
* Returns the style of the drawable to update
*/
@NonNull
- @DevicePolicyResources.UpdatableDrawableStyle
public String getDrawableStyle() {
return mDrawableStyle;
}
@@ -134,7 +131,6 @@
* Returns the source of the drawable to update.
*/
@NonNull
- @DevicePolicyResources.UpdatableDrawableSource
public String getDrawableSource() {
return mDrawableSource;
}
diff --git a/core/java/android/app/admin/DevicePolicyManager.java b/core/java/android/app/admin/DevicePolicyManager.java
index 4c7b910..6298a26 100644
--- a/core/java/android/app/admin/DevicePolicyManager.java
+++ b/core/java/android/app/admin/DevicePolicyManager.java
@@ -21,6 +21,7 @@
import static com.android.internal.util.function.pooled.PooledLambda.obtainMessage;
import android.Manifest.permission;
+import android.accounts.Account;
import android.annotation.CallbackExecutor;
import android.annotation.ColorInt;
import android.annotation.IntDef;
@@ -41,7 +42,6 @@
import android.app.Activity;
import android.app.IServiceConnection;
import android.app.KeyguardManager;
-import android.app.admin.DevicePolicyResources.Drawables;
import android.app.admin.SecurityLog.SecurityEvent;
import android.compat.annotation.UnsupportedAppUsage;
import android.content.ComponentName;
@@ -55,10 +55,8 @@
import android.content.pm.PackageManager.NameNotFoundException;
import android.content.pm.ParceledListSlice;
import android.content.pm.UserInfo;
-import android.content.res.Resources;
import android.graphics.Bitmap;
import android.graphics.drawable.Drawable;
-import android.graphics.drawable.Icon;
import android.net.PrivateDnsConnectivityChecker;
import android.net.ProxyInfo;
import android.net.Uri;
@@ -97,7 +95,6 @@
import android.text.TextUtils;
import android.util.ArraySet;
import android.util.DebugUtils;
-import android.util.DisplayMetrics;
import android.util.Log;
import android.util.Pair;
@@ -138,7 +135,6 @@
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Executor;
import java.util.function.Consumer;
-import java.util.function.Supplier;
// TODO(b/172376923) - add CarDevicePolicyManager examples below (or remove reference to it).
/**
@@ -173,6 +169,7 @@
private final Context mContext;
private final IDevicePolicyManager mService;
private final boolean mParentInstance;
+ private final DevicePolicyResourcesManager mResourcesManager;
/** @hide */
public DevicePolicyManager(Context context, IDevicePolicyManager service) {
@@ -186,6 +183,7 @@
mContext = context;
mService = service;
mParentInstance = parentInstance;
+ mResourcesManager = new DevicePolicyResourcesManager(context, service);
}
/** @hide test will override it. */
@@ -719,10 +717,11 @@
/**
* A {@code boolean} extra which determines whether to force a role holder update, regardless
- * of any internal conditions {@link #ACTION_UPDATE_DEVICE_MANAGEMENT_ROLE_HOLDER} might have.
+ * of any internal conditions {@link #ACTION_UPDATE_DEVICE_POLICY_MANAGEMENT_ROLE_HOLDER} might
+ * have.
*
* <p>This extra can be provided to intents with action {@link
- * #ACTION_UPDATE_DEVICE_MANAGEMENT_ROLE_HOLDER}.
+ * #ACTION_UPDATE_DEVICE_POLICY_MANAGEMENT_ROLE_HOLDER}.
*
* @hide
*/
@@ -1622,14 +1621,26 @@
"android.app.extra.PROVISIONING_SKIP_EDUCATION_SCREENS";
/**
- * A boolean extra indicating if mobile data should be used during NFC device owner provisioning
- * for downloading the mobile device management application. If {@link
- * #EXTRA_PROVISIONING_WIFI_SSID} is also specified, wifi network will be used instead.
+ * A boolean extra indicating if mobile data should be used during the provisioning flow
+ * for downloading the admin app. If {@link #EXTRA_PROVISIONING_WIFI_SSID} is also specified,
+ * wifi network will be used instead.
*
- * <p>Use in an NFC record with {@link #MIME_TYPE_PROVISIONING_NFC} that starts device owner
- * provisioning via an NFC bump.
+ * <p>Default value is {@code false}.
*
- * @hide
+ * <p>If this extra is set to {@code true} and {@link #EXTRA_PROVISIONING_WIFI_SSID} is not
+ * specified, this extra has different behaviour depending on the way provisioning is triggered:
+ * <ul>
+ * <li>
+ * For provisioning started via a QR code or an NFC tag, mobile data is always used for
+ * downloading the admin app.
+ * </li>
+ * <li>
+ * For all other provisioning methods, a mobile data connection check is made at the start
+ * of provisioning. If mobile data is connected at that point, the admin app download will
+ * happen using mobile data. If mobile data is not connected at that point, the end-user
+ * will be asked to pick a wifi network and the admin app download will proceed over wifi.
+ * </li>
+ * </ul>
*/
public static final String EXTRA_PROVISIONING_USE_MOBILE_DATA =
"android.app.extra.PROVISIONING_USE_MOBILE_DATA";
@@ -3281,39 +3292,84 @@
*
* <p>The activity must handle the device policy management role holder update and set the
* intent result to either {@link Activity#RESULT_OK} if the update was successful, {@link
- * #RESULT_UPDATE_DEVICE_MANAGEMENT_ROLE_HOLDER_RECOVERABLE_ERROR} if it encounters a problem
- * that may be solved by relaunching it again, or {@link
- * #RESULT_UPDATE_DEVICE_MANAGEMENT_ROLE_HOLDER_UNRECOVERABLE_ERROR} if it encounters a problem
- * that will not be solved by relaunching it again.
+ * #RESULT_UPDATE_DEVICE_POLICY_MANAGEMENT_ROLE_HOLDER_RECOVERABLE_ERROR} if it encounters a
+ * problem that may be solved by relaunching it again, {@link
+ * #RESULT_UPDATE_DEVICE_POLICY_MANAGEMENT_ROLE_HOLDER_PROVISIONING_DISABLED} if role holder
+ * provisioning is disabled, or {@link
+ * #RESULT_UPDATE_DEVICE_POLICY_MANAGEMENT_ROLE_HOLDER_UNRECOVERABLE_ERROR} if it encounters
+ * any other problem that will not be solved by relaunching it again.
*
* <p>If this activity has additional internal conditions which are not met, it should return
- * {@link #RESULT_UPDATE_DEVICE_MANAGEMENT_ROLE_HOLDER_UNRECOVERABLE_ERROR}.
+ * {@link #RESULT_UPDATE_DEVICE_POLICY_MANAGEMENT_ROLE_HOLDER_UNRECOVERABLE_ERROR}.
*
* @hide
*/
@RequiresPermission(android.Manifest.permission.LAUNCH_DEVICE_MANAGER_SETUP)
@SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
@SystemApi
- public static final String ACTION_UPDATE_DEVICE_MANAGEMENT_ROLE_HOLDER =
- "android.app.action.UPDATE_DEVICE_MANAGEMENT_ROLE_HOLDER";
+ public static final String ACTION_UPDATE_DEVICE_POLICY_MANAGEMENT_ROLE_HOLDER =
+ "android.app.action.UPDATE_DEVICE_POLICY_MANAGEMENT_ROLE_HOLDER";
/**
- * Result code that can be returned by the {@link #ACTION_UPDATE_DEVICE_MANAGEMENT_ROLE_HOLDER}
- * handler if it encounters a problem that may be solved by relaunching it again.
+ * Result code that can be returned by the {@link
+ * #ACTION_UPDATE_DEVICE_POLICY_MANAGEMENT_ROLE_HOLDER} handler if it encounters a problem
+ * that may be solved by relaunching it again.
*
* @hide
*/
@SystemApi
- public static final int RESULT_UPDATE_DEVICE_MANAGEMENT_ROLE_HOLDER_RECOVERABLE_ERROR = 1;
+ public static final int RESULT_UPDATE_DEVICE_POLICY_MANAGEMENT_ROLE_HOLDER_RECOVERABLE_ERROR =
+ 1;
/**
- * Result code that can be returned by the {@link #ACTION_UPDATE_DEVICE_MANAGEMENT_ROLE_HOLDER}
- * handler if it encounters a problem that will not be solved by relaunching it again.
+ * Result code that can be returned by the {@link
+ * #ACTION_UPDATE_DEVICE_POLICY_MANAGEMENT_ROLE_HOLDER} handler if it encounters a problem that
+ * will not be solved by relaunching it again.
*
* @hide
*/
@SystemApi
- public static final int RESULT_UPDATE_DEVICE_MANAGEMENT_ROLE_HOLDER_UNRECOVERABLE_ERROR = 2;
+ public static final int RESULT_UPDATE_DEVICE_POLICY_MANAGEMENT_ROLE_HOLDER_UNRECOVERABLE_ERROR =
+ 2;
+
+ /**
+ * Result code that can be returned by the {@link
+ * #ACTION_UPDATE_DEVICE_POLICY_MANAGEMENT_ROLE_HOLDER} handler if role holder provisioning
+ * is disabled.
+ *
+ * @hide
+ */
+ @SystemApi
+ public static final int
+ RESULT_UPDATE_DEVICE_POLICY_MANAGEMENT_ROLE_HOLDER_PROVISIONING_DISABLED = 3;
+
+ /**
+ * An {@code int} extra which contains the result code of the last attempt to update
+ * the device policy management role holder.
+ *
+ * <p>This extra is provided to the device policy management role holder via either {@link
+ * #ACTION_ROLE_HOLDER_PROVISION_MANAGED_DEVICE_FROM_TRUSTED_SOURCE} or {@link
+ * #ACTION_ROLE_HOLDER_PROVISION_MANAGED_PROFILE} when started after the role holder
+ * had previously returned {@link #RESULT_UPDATE_ROLE_HOLDER}.
+ *
+ * <p>If the role holder update had failed, the role holder can use the value of this extra to
+ * make a decision whether to fail the provisioning flow or to carry on with the older version
+ * of the role holder.
+ *
+ * <p>Possible values can be:
+ * <ul>
+ * <li>{@link Activity#RESULT_OK} if the update was successful
+ * <li>{@link #RESULT_UPDATE_DEVICE_POLICY_MANAGEMENT_ROLE_HOLDER_RECOVERABLE_ERROR} if it
+ * encounters a problem that may be solved by relaunching it again.
+ * <li>{@link #RESULT_UPDATE_DEVICE_POLICY_MANAGEMENT_ROLE_HOLDER_UNRECOVERABLE_ERROR} if
+ * it encounters a problem that will not be solved by relaunching it again.
+ * </ul>
+ *
+ * @hide
+ */
+ @SystemApi
+ public static final String EXTRA_ROLE_HOLDER_UPDATE_RESULT_CODE =
+ "android.app.extra.ROLE_HOLDER_UPDATE_RESULT_CODE";
/**
* An {@link Intent} extra which resolves to a custom user consent screen.
@@ -3335,6 +3391,16 @@
* <li>General disclaimer relevant to the provisioning mode</li>
* </ul>
*
+ * <p>When this {@link Intent} is started, the following intent extras will be supplied:
+ * <ul>
+ * <li>{@link #EXTRA_PROVISIONING_DISCLAIMERS}</li>
+ * <li>{@link #EXTRA_PROVISIONING_MODE}</li>
+ * <li>{@link #EXTRA_PROVISIONING_LOCALE}</li>
+ * <li>{@link #EXTRA_PROVISIONING_LOCAL_TIME}</li>
+ * <li>{@link #EXTRA_PROVISIONING_TIME_ZONE}</li>
+ * <li>{@link #EXTRA_PROVISIONING_SKIP_EDUCATION_SCREENS}</li>
+ * </ul>
+ *
* <p>If the custom consent screens are granted by the user {@link Activity#RESULT_OK} is
* returned, otherwise {@link Activity#RESULT_CANCELED} is returned. The device policy
* management role holder should ensure that the provisioning flow terminates immediately if
@@ -3669,7 +3735,8 @@
/**
* Broadcast action: notify system apps (e.g. settings, SysUI, etc) that the device management
* resources with IDs {@link #EXTRA_RESOURCE_IDS} has been updated, the updated resources can be
- * retrieved using {@link #getDrawable} and {@code #getString}.
+ * retrieved using {@link DevicePolicyResourcesManager#getDrawable} and
+ * {@link DevicePolicyResourcesManager#getString}.
*
* <p>This broadcast is sent to registered receivers only.
*
@@ -14004,12 +14071,12 @@
/**
* Deprecated. Use {@code markProfileOwnerOnOrganizationOwnedDevice} instead.
* When called by an app targeting SDK level {@link android.os.Build.VERSION_CODES#Q} or
- * below, will behave the same as {@link #markProfileOwnerOnOrganizationOwnedDevice}.
+ * below, will behave the same as {@link #setProfileOwnerOnOrganizationOwnedDevice}.
*
* When called by an app targeting SDK level {@link android.os.Build.VERSION_CODES#R}
* or above, will throw an UnsupportedOperationException when called.
*
- * @deprecated Use {@link #markProfileOwnerOnOrganizationOwnedDevice} instead.
+ * @deprecated Use {@link #setProfileOwnerOnOrganizationOwnedDevice} instead.
*
* @hide
*/
@@ -14024,14 +14091,14 @@
"This method is deprecated. use markProfileOwnerOnOrganizationOwnedDevice"
+ " instead.");
} else {
- markProfileOwnerOnOrganizationOwnedDevice(who);
+ setProfileOwnerOnOrganizationOwnedDevice(who, true);
}
}
/**
- * Marks the profile owner of the given user as managing an organization-owned device.
- * That will give it access to device identifiers (such as serial number, IMEI and MEID)
- * as well as other privileges.
+ * Sets whether the profile owner of the given user as managing an organization-owned device.
+ * Managing an organization-owned device will give it access to device identifiers (such as
+ * serial number, IMEI and MEID) as well as other privileges.
*
* @hide
*/
@@ -14039,13 +14106,15 @@
@RequiresPermission(anyOf = {
android.Manifest.permission.MARK_DEVICE_ORGANIZATION_OWNED,
android.Manifest.permission.MANAGE_PROFILE_AND_DEVICE_OWNERS
- }, conditional = true)
- public void markProfileOwnerOnOrganizationOwnedDevice(@NonNull ComponentName who) {
+ }, conditional = true)
+ public void setProfileOwnerOnOrganizationOwnedDevice(@NonNull ComponentName who,
+ boolean isProfileOwnerOnOrganizationOwnedDevice) {
if (mService == null) {
return;
}
try {
- mService.markProfileOwnerOnOrganizationOwnedDevice(who, myUserId());
+ mService.setProfileOwnerOnOrganizationOwnedDevice(who, myUserId(),
+ isProfileOwnerOnOrganizationOwnedDevice);
} catch (RemoteException re) {
throw re.rethrowFromSystemServer();
}
@@ -14795,6 +14864,28 @@
}
/**
+ * Called when a managed profile has been provisioned.
+ *
+ * @throws SecurityException if the caller does not hold
+ * {@link android.Manifest.permission#MANAGE_PROFILE_AND_DEVICE_OWNERS}.
+ * @hide
+ */
+ @SystemApi
+ @RequiresPermission(android.Manifest.permission.MANAGE_PROFILE_AND_DEVICE_OWNERS)
+ public void finalizeWorkProfileProvisioning(
+ @NonNull UserHandle managedProfileUser, @Nullable Account migratedAccount) {
+ Objects.requireNonNull(managedProfileUser, "managedProfileUser can't be null");
+ if (mService == null) {
+ throw new IllegalStateException("Could not find DevicePolicyManagerService");
+ }
+ try {
+ mService.finalizeWorkProfileProvisioning(managedProfileUser, migratedAccount);
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+
+ /**
* The localized error message to show to the end-user. If {@code null}, a generic error
* message will be shown.
*/
@@ -15202,481 +15293,12 @@
}
/**
- * For each {@link DevicePolicyDrawableResource} item in {@code drawables}, if
- * {@link DevicePolicyDrawableResource#getDrawableSource()} is not set or is set to
- * {@link DevicePolicyResources.Drawables.Source#UNDEFINED}, it updates the drawable resource for
- * the combination of {@link DevicePolicyDrawableResource#getDrawableId()} and
- * {@link DevicePolicyDrawableResource#getDrawableStyle()}, (see
- * {@link DevicePolicyResources.Drawables} and {@link DevicePolicyResources.Drawables.Style}) to
- * the drawable with ID {@link DevicePolicyDrawableResource#getResourceIdInCallingPackage()},
- * meaning any system UI surface calling {@link #getDrawable}
- * with {@code drawableId} and {@code drawableStyle} will get the new resource after this API
- * is called.
- *
- * <p>Otherwise, if {@link DevicePolicyDrawableResource#getDrawableSource()} is set (see
- * {@link DevicePolicyResources.Drawables.Source}, it overrides any drawables that was set for
- * the same {@code drawableId} and {@code drawableStyle} for the provided source.
- *
- * <p>Sends a broadcast with action {@link #ACTION_DEVICE_POLICY_RESOURCE_UPDATED} to
- * registered receivers when a resource has been updated successfully.
- *
- * <p>Important notes to consider when using this API:
- * <ul>
- * <li>{@link #getDrawable} references the resource
- * {@link DevicePolicyDrawableResource#getResourceIdInCallingPackage()} in the
- * calling package each time it gets called. You have to ensure that the resource is always
- * available in the calling package as long as it is used as an updated resource.
- * <li>You still have to re-call {@code setDrawables} even if you only make changes to the
- * content of the resource with ID
- * {@link DevicePolicyDrawableResource#getResourceIdInCallingPackage()} as the content might be
- * cached and would need updating.
- * </ul>
- *
- * @param drawables The list of {@link DevicePolicyDrawableResource} to update.
- *
- * @hide
+ * Returns a {@link DevicePolicyResourcesManager} containing the required APIs to set, reset,
+ * and get device policy related resources.
*/
- @SystemApi
- @RequiresPermission(android.Manifest.permission.UPDATE_DEVICE_MANAGEMENT_RESOURCES)
- public void setDrawables(@NonNull Set<DevicePolicyDrawableResource> drawables) {
- if (mService != null) {
- try {
- mService.setDrawables(new ArrayList<>(drawables));
- } catch (RemoteException e) {
- throw e.rethrowFromSystemServer();
- }
- }
- }
-
- /**
- * Removes all updated drawables for the list of {@code drawableIds} (see
- * {@link DevicePolicyResources.Drawables} that was previously set by calling
- * {@link #setDrawables}, meaning any subsequent calls to {@link #getDrawable} for the provided
- * IDs with any {@link DevicePolicyResources.Drawables.Style} and any
- * {@link DevicePolicyResources.Drawables.Source} will return the default drawable from
- * {@code defaultDrawableLoader}.
- *
- * <p>Sends a broadcast with action {@link #ACTION_DEVICE_POLICY_RESOURCE_UPDATED} to
- * registered receivers when a resource has been reset successfully.
- *
- * @param drawableIds The list of IDs to remove.
- *
- * @hide
- */
- @SystemApi
- @RequiresPermission(android.Manifest.permission.UPDATE_DEVICE_MANAGEMENT_RESOURCES)
- public void resetDrawables(@NonNull String[] drawableIds) {
- if (mService != null) {
- try {
- mService.resetDrawables(drawableIds);
- } catch (RemoteException e) {
- throw e.rethrowFromSystemServer();
- }
- }
- }
-
- /**
- * Returns the appropriate updated drawable for the {@code drawableId}
- * (see {@link DevicePolicyResources.Drawables}), with style {@code drawableStyle}
- * (see {@link DevicePolicyResources.Drawables.Style}) if one was set using
- * {@code setDrawables}, otherwise returns the drawable from {@code defaultDrawableLoader}.
- *
- * <p>Also returns the drawable from {@code defaultDrawableLoader} if
- * {@link DevicePolicyResources.Drawables#UNDEFINED} was passed.
- *
- * <p>Calls to this API will not return {@code null} unless no updated drawable was found
- * and the call to {@code defaultDrawableLoader} returned {@code null}.
- *
- * <p>This API uses the screen density returned from {@link Resources#getConfiguration()}, to
- * set a different value use
- * {@link #getDrawableForDensity(String, String, int, Supplier)}.
- *
- * <p>Callers should register for {@link #ACTION_DEVICE_POLICY_RESOURCE_UPDATED} to get
- * notified when a resource has been updated.
- *
- * <p>Note that each call to this API loads the resource from the package that called
- * {@code setDrawables} to set the updated resource.
- *
- * @param drawableId The drawable ID to get the updated resource for.
- * @param drawableStyle The drawable style to use.
- * @param defaultDrawableLoader To get the default drawable if no updated drawable was set for
- * the provided params.
- */
- @Nullable
- public Drawable getDrawable(
- @NonNull @DevicePolicyResources.UpdatableDrawableId String drawableId,
- @NonNull @DevicePolicyResources.UpdatableDrawableStyle String drawableStyle,
- @NonNull Supplier<Drawable> defaultDrawableLoader) {
- return getDrawable(
- drawableId, drawableStyle, Drawables.Source.UNDEFINED, defaultDrawableLoader);
- }
-
- /**
- * Similar to {@link #getDrawable(String, String, Supplier)}, but also accepts
- * a {@code drawableSource} (see {@link DevicePolicyResources.Drawables.Source}) which
- * could result in returning a different drawable than
- * {@link #getDrawable(String, String, Supplier)}
- * if an override was set for that specific source.
- *
- * <p>Calls to this API will not return {@code null} unless no updated drawable was found
- * and the call to {@code defaultDrawableLoader} returned {@code null}.
- *
- * <p>Callers should register for {@link #ACTION_DEVICE_POLICY_RESOURCE_UPDATED} to get
- * notified when a resource has been updated.
- *
- * @param drawableId The drawable ID to get the updated resource for.
- * @param drawableStyle The drawable style to use.
- * @param drawableSource The source for the caller.
- * @param defaultDrawableLoader To get the default drawable if no updated drawable was set for
- * the provided params.
- */
- @Nullable
- public Drawable getDrawable(
- @NonNull @DevicePolicyResources.UpdatableDrawableId String drawableId,
- @NonNull @DevicePolicyResources.UpdatableDrawableStyle String drawableStyle,
- @NonNull @DevicePolicyResources.UpdatableDrawableSource String drawableSource,
- @NonNull Supplier<Drawable> defaultDrawableLoader) {
-
- Objects.requireNonNull(drawableId, "drawableId can't be null");
- Objects.requireNonNull(drawableStyle, "drawableStyle can't be null");
- Objects.requireNonNull(drawableSource, "drawableSource can't be null");
- Objects.requireNonNull(defaultDrawableLoader, "defaultDrawableLoader can't be null");
-
- if (Drawables.UNDEFINED.equals(drawableId)) {
- return ParcelableResource.loadDefaultDrawable(defaultDrawableLoader);
- }
- if (mService != null) {
- try {
- ParcelableResource resource = mService.getDrawable(
- drawableId, drawableStyle, drawableSource);
- if (resource == null) {
- return ParcelableResource.loadDefaultDrawable(
- defaultDrawableLoader);
- }
- return resource.getDrawable(
- mContext,
- /* density= */ 0,
- defaultDrawableLoader);
-
- } catch (RemoteException e) {
- Log.e(
- TAG,
- "Error getting the updated drawable from DevicePolicyManagerService.",
- e);
- return ParcelableResource.loadDefaultDrawable(defaultDrawableLoader);
- }
- }
- return ParcelableResource.loadDefaultDrawable(defaultDrawableLoader);
- }
-
- /**
- * Similar to {@link #getDrawable(String, String, Supplier)}, but also accepts
- * {@code density}. See {@link Resources#getDrawableForDensity(int, int, Resources.Theme)}.
- *
- * <p>Calls to this API will not return {@code null} unless no updated drawable was found
- * and the call to {@code defaultDrawableLoader} returned {@code null}.
- *
- * <p>Callers should register for {@link #ACTION_DEVICE_POLICY_RESOURCE_UPDATED} to get
- * notified when a resource has been updated.
- *
- * @param drawableId The drawable ID to get the updated resource for.
- * @param drawableStyle The drawable style to use.
- * @param density The desired screen density indicated by the resource as
- * found in {@link DisplayMetrics}. A value of 0 means to use the
- * density returned from {@link Resources#getConfiguration()}.
- * @param defaultDrawableLoader To get the default drawable if no updated drawable was set for
- * the provided params.
- */
- @Nullable
- public Drawable getDrawableForDensity(
- @NonNull @DevicePolicyResources.UpdatableDrawableId String drawableId,
- @NonNull @DevicePolicyResources.UpdatableDrawableStyle String drawableStyle,
- int density,
- @NonNull Supplier<Drawable> defaultDrawableLoader) {
- return getDrawableForDensity(
- drawableId,
- drawableStyle,
- Drawables.Source.UNDEFINED,
- density,
- defaultDrawableLoader);
- }
-
- /**
- * Similar to {@link #getDrawable(String, String, String, Supplier)}, but also accepts
- * {@code density}. See {@link Resources#getDrawableForDensity(int, int, Resources.Theme)}.
- *
- * <p>Calls to this API will not return {@code null} unless no updated drawable was found
- * and the call to {@code defaultDrawableLoader} returned {@code null}.
- *
- * <p>Callers should register for {@link #ACTION_DEVICE_POLICY_RESOURCE_UPDATED} to get
- * notified when a resource has been updated.
- *
- * @param drawableId The drawable ID to get the updated resource for.
- * @param drawableStyle The drawable style to use.
- * @param drawableSource The source for the caller.
- * @param density The desired screen density indicated by the resource as
- * found in {@link DisplayMetrics}. A value of 0 means to use the
- * density returned from {@link Resources#getConfiguration()}.
- * @param defaultDrawableLoader To get the default drawable if no updated drawable was set for
- * the provided params.
- */
- @Nullable
- public Drawable getDrawableForDensity(
- @NonNull @DevicePolicyResources.UpdatableDrawableId String drawableId,
- @NonNull @DevicePolicyResources.UpdatableDrawableStyle String drawableStyle,
- @NonNull @DevicePolicyResources.UpdatableDrawableSource String drawableSource,
- int density,
- @NonNull Supplier<Drawable> defaultDrawableLoader) {
-
- Objects.requireNonNull(drawableId, "drawableId can't be null");
- Objects.requireNonNull(drawableStyle, "drawableStyle can't be null");
- Objects.requireNonNull(drawableSource, "drawableSource can't be null");
- Objects.requireNonNull(defaultDrawableLoader, "defaultDrawableLoader can't be null");
-
- if (Drawables.UNDEFINED.equals(drawableId)) {
- return ParcelableResource.loadDefaultDrawable(defaultDrawableLoader);
- }
- if (mService != null) {
- try {
- ParcelableResource resource = mService.getDrawable(
- drawableId, drawableStyle, drawableSource);
- if (resource == null) {
- return ParcelableResource.loadDefaultDrawable(
- defaultDrawableLoader);
- }
- return resource.getDrawable(mContext, density, defaultDrawableLoader);
- } catch (RemoteException e) {
- Log.e(
- TAG,
- "Error getting the updated drawable from DevicePolicyManagerService.",
- e);
- return ParcelableResource.loadDefaultDrawable(defaultDrawableLoader);
- }
- }
- return ParcelableResource.loadDefaultDrawable(defaultDrawableLoader);
- }
-
- /**
- * Similar to {@link #getDrawable(String, String, String, Supplier)} but returns an
- * {@link Icon} instead of a {@link Drawable}.
- *
- * @param drawableId The drawable ID to get the updated resource for.
- * @param drawableStyle The drawable style to use.
- * @param drawableSource The source for the caller.
- * @param defaultIcon Returned if no updated drawable was set for the provided params.
- */
- @Nullable
- public Icon getDrawableAsIcon(
- @NonNull @DevicePolicyResources.UpdatableDrawableId String drawableId,
- @NonNull @DevicePolicyResources.UpdatableDrawableStyle String drawableStyle,
- @NonNull @DevicePolicyResources.UpdatableDrawableSource String drawableSource,
- @Nullable Icon defaultIcon) {
- Objects.requireNonNull(drawableId, "drawableId can't be null");
- Objects.requireNonNull(drawableStyle, "drawableStyle can't be null");
- Objects.requireNonNull(drawableSource, "drawableSource can't be null");
- Objects.requireNonNull(defaultIcon, "defaultIcon can't be null");
-
- if (Drawables.UNDEFINED.equals(drawableId)) {
- return defaultIcon;
- }
- if (mService != null) {
- try {
- ParcelableResource resource = mService.getDrawable(
- drawableId, drawableStyle, drawableSource);
- if (resource == null) {
- return defaultIcon;
- }
- return Icon.createWithResource(resource.getPackageName(), resource.getResourceId());
- } catch (RemoteException e) {
- Log.e(
- TAG,
- "Error getting the updated drawable from DevicePolicyManagerService.",
- e);
- return defaultIcon;
- }
- }
- return defaultIcon;
- }
-
- /**
- * Similar to {@link #getDrawable(String, String, Supplier)} but returns an {@link Icon}
- * instead of a {@link Drawable}.
- *
- * @param drawableId The drawable ID to get the updated resource for.
- * @param drawableStyle The drawable style to use.
- * @param defaultIcon Returned if no updated drawable was set for the provided params.
- */
- @Nullable
- public Icon getDrawableAsIcon(
- @NonNull @DevicePolicyResources.UpdatableDrawableId String drawableId,
- @NonNull @DevicePolicyResources.UpdatableDrawableStyle String drawableStyle,
- @Nullable Icon defaultIcon) {
- return getDrawableAsIcon(
- drawableId, drawableStyle, Drawables.Source.UNDEFINED, defaultIcon);
- }
-
-
- /**
- * For each {@link DevicePolicyStringResource} item in {@code strings}, it updates the string
- * resource for {@link DevicePolicyStringResource#getStringId()} to the string with ID
- * {@code callingPackageResourceId} (see {@link DevicePolicyResources.Strings}), meaning any
- * system UI surface calling {@link #getString} with {@code stringId} will get
- * the new resource after this API is called.
- *
- * <p>Sends a broadcast with action {@link #ACTION_DEVICE_POLICY_RESOURCE_UPDATED} to
- * registered receivers when a resource has been updated successfully.
- *
- * <p>Important notes to consider when using this API:
- * <ul>
- * <li> {@link #getString} references the resource
- * {@code callingPackageResourceId} in the calling package each time it gets called. You have to
- * ensure that the resource is always available in the calling package as long as it is used as
- * an updated resource.
- * <li> You still have to re-call {@code setStrings} even if you only make changes to the
- * content of the resource with ID {@code callingPackageResourceId} as the content might be
- * cached and would need updating.
- * </ul>
- *
- * @param strings The list of {@link DevicePolicyStringResource} to update.
- *
- * @hide
- */
- @SystemApi
- @RequiresPermission(android.Manifest.permission.UPDATE_DEVICE_MANAGEMENT_RESOURCES)
- public void setStrings(@NonNull Set<DevicePolicyStringResource> strings) {
- if (mService != null) {
- try {
- mService.setStrings(new ArrayList<>(strings));
- } catch (RemoteException e) {
- throw e.rethrowFromSystemServer();
- }
- }
- }
-
- /**
- * Removes the updated strings for the list of {@code stringIds} (see
- * {@link DevicePolicyResources.Strings}) that was previously set by calling {@link #setStrings},
- * meaning any subsequent calls to {@link #getString} for the provided IDs will
- * return the default string from {@code defaultStringLoader}.
- *
- * <p>Sends a broadcast with action {@link #ACTION_DEVICE_POLICY_RESOURCE_UPDATED} to
- * registered receivers when a resource has been reset successfully.
- *
- * @param stringIds The list of IDs to remove the updated resources for.
- *
- * @hide
- */
- @SystemApi
- @RequiresPermission(android.Manifest.permission.UPDATE_DEVICE_MANAGEMENT_RESOURCES)
- public void resetStrings(@NonNull String[] stringIds) {
- if (mService != null) {
- try {
- mService.resetStrings(stringIds);
- } catch (RemoteException e) {
- throw e.rethrowFromSystemServer();
- }
- }
- }
-
- /**
- * Returns the appropriate updated string for the {@code stringId} (see
- * {@link DevicePolicyResources.Strings}) if one was set using
- * {@link #setStrings}, otherwise returns the string from {@code defaultStringLoader}.
- *
- * <p>Also returns the string from {@code defaultStringLoader} if
- * {@link DevicePolicyResources.Strings#UNDEFINED} was passed.
- *
- * <p>Calls to this API will not return {@code null} unless no updated drawable was found
- * and the call to {@code defaultStringLoader} returned {@code null}.
- *
- * <p>Callers should register for {@link #ACTION_DEVICE_POLICY_RESOURCE_UPDATED} to get
- * notified when a resource has been updated.
- *
- * <p>Note that each call to this API loads the resource from the package that called
- * {@link #setStrings} to set the updated resource.
- *
- * @param stringId The IDs to get the updated resource for.
- * @param defaultStringLoader To get the default string if no updated string was set for
- * {@code stringId}.
- *
- * @hide
- */
- @SystemApi
- @Nullable
- public String getString(
- @NonNull @DevicePolicyResources.UpdatableStringId String stringId,
- @NonNull Supplier<String> defaultStringLoader) {
-
- Objects.requireNonNull(stringId, "stringId can't be null");
- Objects.requireNonNull(defaultStringLoader, "defaultStringLoader can't be null");
-
- if (stringId.equals(DevicePolicyResources.Strings.UNDEFINED)) {
- return ParcelableResource.loadDefaultString(defaultStringLoader);
- }
- if (mService != null) {
- try {
- ParcelableResource resource = mService.getString(stringId);
- if (resource == null) {
- return ParcelableResource.loadDefaultString(defaultStringLoader);
- }
- return resource.getString(mContext, defaultStringLoader);
- } catch (RemoteException e) {
- Log.e(
- TAG,
- "Error getting the updated string from DevicePolicyManagerService.",
- e);
- return ParcelableResource.loadDefaultString(defaultStringLoader);
- }
- }
- return ParcelableResource.loadDefaultString(defaultStringLoader);
- }
-
- /**
- * Similar to {@link #getString(String, Supplier)} but accepts {@code formatArgs} and returns a
- * localized formatted string, substituting the format arguments as defined in
- * {@link java.util.Formatter} and {@link java.lang.String#format}, (see
- * {@link Resources#getString(int, Object...)}).
- *
- * <p>Calls to this API will not return {@code null} unless no updated drawable was found
- * and the call to {@code defaultStringLoader} returned {@code null}.
- *
- * @param stringId The IDs to get the updated resource for.
- * @param defaultStringLoader To get the default string if no updated string was set for
- * {@code stringId}.
- * @param formatArgs The format arguments that will be used for substitution.
- *
- * @hide
- */
- @SystemApi
- @Nullable
- @SuppressLint("SamShouldBeLast")
- public String getString(
- @NonNull @DevicePolicyResources.UpdatableStringId String stringId,
- @NonNull Supplier<String> defaultStringLoader,
- @NonNull Object... formatArgs) {
-
- Objects.requireNonNull(stringId, "stringId can't be null");
- Objects.requireNonNull(defaultStringLoader, "defaultStringLoader can't be null");
-
- if (stringId.equals(DevicePolicyResources.Strings.UNDEFINED)) {
- return ParcelableResource.loadDefaultString(defaultStringLoader);
- }
- if (mService != null) {
- try {
- ParcelableResource resource = mService.getString(stringId);
- if (resource == null) {
- return ParcelableResource.loadDefaultString(defaultStringLoader);
- }
- return resource.getString(mContext, defaultStringLoader, formatArgs);
- } catch (RemoteException e) {
- Log.e(
- TAG,
- "Error getting the updated string from DevicePolicyManagerService.",
- e);
- return ParcelableResource.loadDefaultString(defaultStringLoader);
- }
- }
- return ParcelableResource.loadDefaultString(defaultStringLoader);
+ @NonNull
+ public DevicePolicyResourcesManager getResources() {
+ return mResourcesManager;
}
/**
@@ -15732,9 +15354,28 @@
*/
@Nullable
public String getDevicePolicyManagementRoleHolderPackage() {
- String deviceManagerConfig = mContext.getString(
+ String devicePolicyManagementConfig = mContext.getString(
com.android.internal.R.string.config_devicePolicyManagement);
- return extractPackageNameFromDeviceManagerConfig(deviceManagerConfig);
+ return extractPackageNameFromDeviceManagerConfig(devicePolicyManagementConfig);
+ }
+
+ /**
+ * Returns the package name of the device policy management role holder updater.
+ *
+ * <p>If the device policy management role holder updater is not configured for this device,
+ * returns {@code null}.
+ *
+ * @hide
+ */
+ @Nullable
+ @TestApi
+ public String getDevicePolicyManagementRoleHolderUpdaterPackage() {
+ String devicePolicyManagementUpdaterConfig = mContext.getString(
+ com.android.internal.R.string.config_devicePolicyManagementUpdater);
+ if (TextUtils.isEmpty(devicePolicyManagementUpdaterConfig)) {
+ return null;
+ }
+ return devicePolicyManagementUpdaterConfig;
}
/**
@@ -15760,4 +15401,23 @@
}
return deviceManagerConfig;
}
+
+ /**
+ * @return {@code true} if bypassing the device policy management role qualification is allowed
+ * with the current state of the device.
+ *
+ * @hide
+ */
+ @SystemApi
+ @RequiresPermission(android.Manifest.permission.MANAGE_ROLE_HOLDERS)
+ public boolean shouldAllowBypassingDevicePolicyManagementRoleQualification() {
+ if (mService != null) {
+ try {
+ return mService.shouldAllowBypassingDevicePolicyManagementRoleQualification();
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+ return false;
+ }
}
diff --git a/core/java/android/app/admin/DevicePolicyResources.java b/core/java/android/app/admin/DevicePolicyResources.java
index 042e407..2b3780e 100644
--- a/core/java/android/app/admin/DevicePolicyResources.java
+++ b/core/java/android/app/admin/DevicePolicyResources.java
@@ -16,519 +16,32 @@
package android.app.admin;
-import static android.app.admin.DevicePolicyResources.Strings.Core.CANT_ADD_ACCOUNT_MESSAGE;
-import static android.app.admin.DevicePolicyResources.Strings.Core.FORWARD_INTENT_TO_PERSONAL;
-import static android.app.admin.DevicePolicyResources.Strings.Core.FORWARD_INTENT_TO_WORK;
-import static android.app.admin.DevicePolicyResources.Strings.Core.LOCATION_CHANGED_MESSAGE;
-import static android.app.admin.DevicePolicyResources.Strings.Core.LOCATION_CHANGED_TITLE;
-import static android.app.admin.DevicePolicyResources.Strings.Core.NETWORK_LOGGING_MESSAGE;
-import static android.app.admin.DevicePolicyResources.Strings.Core.NETWORK_LOGGING_TITLE;
-import static android.app.admin.DevicePolicyResources.Strings.Core.NOTIFICATION_CHANNEL_DEVICE_ADMIN;
-import static android.app.admin.DevicePolicyResources.Strings.Core.NOTIFICATION_WORK_PROFILE_CONTENT_DESCRIPTION;
-import static android.app.admin.DevicePolicyResources.Strings.Core.PACKAGE_DELETED_BY_DO;
-import static android.app.admin.DevicePolicyResources.Strings.Core.PACKAGE_INSTALLED_BY_DO;
-import static android.app.admin.DevicePolicyResources.Strings.Core.PACKAGE_UPDATED_BY_DO;
-import static android.app.admin.DevicePolicyResources.Strings.Core.PERSONAL_APP_SUSPENSION_MESSAGE;
-import static android.app.admin.DevicePolicyResources.Strings.Core.PERSONAL_APP_SUSPENSION_SOON_MESSAGE;
-import static android.app.admin.DevicePolicyResources.Strings.Core.PERSONAL_APP_SUSPENSION_TITLE;
-import static android.app.admin.DevicePolicyResources.Strings.Core.PERSONAL_APP_SUSPENSION_TURN_ON_PROFILE;
-import static android.app.admin.DevicePolicyResources.Strings.Core.PRINTING_DISABLED_NAMED_ADMIN;
-import static android.app.admin.DevicePolicyResources.Strings.Core.PROFILE_ENCRYPTED_DETAIL;
-import static android.app.admin.DevicePolicyResources.Strings.Core.PROFILE_ENCRYPTED_MESSAGE;
-import static android.app.admin.DevicePolicyResources.Strings.Core.PROFILE_ENCRYPTED_TITLE;
-import static android.app.admin.DevicePolicyResources.Strings.Core.RESOLVER_CANT_ACCESS_PERSONAL;
-import static android.app.admin.DevicePolicyResources.Strings.Core.RESOLVER_CANT_ACCESS_WORK;
-import static android.app.admin.DevicePolicyResources.Strings.Core.RESOLVER_CANT_SHARE_WITH_PERSONAL;
-import static android.app.admin.DevicePolicyResources.Strings.Core.RESOLVER_CANT_SHARE_WITH_WORK;
-import static android.app.admin.DevicePolicyResources.Strings.Core.RESOLVER_CROSS_PROFILE_BLOCKED_TITLE;
-import static android.app.admin.DevicePolicyResources.Strings.Core.RESOLVER_NO_PERSONAL_APPS;
-import static android.app.admin.DevicePolicyResources.Strings.Core.RESOLVER_NO_WORK_APPS;
-import static android.app.admin.DevicePolicyResources.Strings.Core.RESOLVER_PERSONAL_TAB;
-import static android.app.admin.DevicePolicyResources.Strings.Core.RESOLVER_PERSONAL_TAB_ACCESSIBILITY;
-import static android.app.admin.DevicePolicyResources.Strings.Core.RESOLVER_WORK_PAUSED_TITLE;
-import static android.app.admin.DevicePolicyResources.Strings.Core.RESOLVER_WORK_PROFILE_NOT_SUPPORTED;
-import static android.app.admin.DevicePolicyResources.Strings.Core.RESOLVER_WORK_TAB;
-import static android.app.admin.DevicePolicyResources.Strings.Core.RESOLVER_WORK_TAB_ACCESSIBILITY;
-import static android.app.admin.DevicePolicyResources.Strings.Core.SWITCH_TO_PERSONAL_LABEL;
-import static android.app.admin.DevicePolicyResources.Strings.Core.SWITCH_TO_WORK_LABEL;
-import static android.app.admin.DevicePolicyResources.Strings.Core.UNLAUNCHABLE_APP_WORK_PAUSED_MESSAGE;
-import static android.app.admin.DevicePolicyResources.Strings.Core.UNLAUNCHABLE_APP_WORK_PAUSED_TITLE;
-import static android.app.admin.DevicePolicyResources.Strings.Core.WORK_PROFILE_BADGED_LABEL;
-import static android.app.admin.DevicePolicyResources.Strings.Core.WORK_PROFILE_DELETED_FAILED_PASSWORD_ATTEMPTS_MESSAGE;
-import static android.app.admin.DevicePolicyResources.Strings.Core.WORK_PROFILE_DELETED_GENERIC_MESSAGE;
-import static android.app.admin.DevicePolicyResources.Strings.Core.WORK_PROFILE_DELETED_ORG_OWNED_MESSAGE;
-import static android.app.admin.DevicePolicyResources.Strings.Core.WORK_PROFILE_DELETED_TITLE;
-import static android.app.admin.DevicePolicyResources.Strings.Dialer.NOTIFICATION_INCOMING_WORK_CALL_TITLE;
-import static android.app.admin.DevicePolicyResources.Strings.Dialer.NOTIFICATION_MISSED_WORK_CALL_TITLE;
-import static android.app.admin.DevicePolicyResources.Strings.Dialer.NOTIFICATION_ONGOING_WORK_CALL_TITLE;
-import static android.app.admin.DevicePolicyResources.Strings.Dialer.NOTIFICATION_WIFI_WORK_CALL_LABEL;
-import static android.app.admin.DevicePolicyResources.Strings.DocumentsUi.CANT_SAVE_TO_PERSONAL_MESSAGE;
-import static android.app.admin.DevicePolicyResources.Strings.DocumentsUi.CANT_SAVE_TO_PERSONAL_TITLE;
-import static android.app.admin.DevicePolicyResources.Strings.DocumentsUi.CANT_SAVE_TO_WORK_MESSAGE;
-import static android.app.admin.DevicePolicyResources.Strings.DocumentsUi.CANT_SAVE_TO_WORK_TITLE;
-import static android.app.admin.DevicePolicyResources.Strings.DocumentsUi.CANT_SELECT_PERSONAL_FILES_MESSAGE;
-import static android.app.admin.DevicePolicyResources.Strings.DocumentsUi.CANT_SELECT_PERSONAL_FILES_TITLE;
-import static android.app.admin.DevicePolicyResources.Strings.DocumentsUi.CANT_SELECT_WORK_FILES_MESSAGE;
-import static android.app.admin.DevicePolicyResources.Strings.DocumentsUi.CANT_SELECT_WORK_FILES_TITLE;
-import static android.app.admin.DevicePolicyResources.Strings.DocumentsUi.CROSS_PROFILE_NOT_ALLOWED_MESSAGE;
-import static android.app.admin.DevicePolicyResources.Strings.DocumentsUi.CROSS_PROFILE_NOT_ALLOWED_TITLE;
-import static android.app.admin.DevicePolicyResources.Strings.DocumentsUi.PERSONAL_TAB;
-import static android.app.admin.DevicePolicyResources.Strings.DocumentsUi.PREVIEW_WORK_FILE_ACCESSIBILITY;
-import static android.app.admin.DevicePolicyResources.Strings.DocumentsUi.WORK_ACCESSIBILITY;
-import static android.app.admin.DevicePolicyResources.Strings.DocumentsUi.WORK_PROFILE_OFF_ENABLE_BUTTON;
-import static android.app.admin.DevicePolicyResources.Strings.DocumentsUi.WORK_PROFILE_OFF_ERROR_TITLE;
-import static android.app.admin.DevicePolicyResources.Strings.DocumentsUi.WORK_TAB;
-import static android.app.admin.DevicePolicyResources.Strings.Launcher.ALL_APPS_PERSONAL_TAB;
-import static android.app.admin.DevicePolicyResources.Strings.Launcher.ALL_APPS_PERSONAL_TAB_ACCESSIBILITY;
-import static android.app.admin.DevicePolicyResources.Strings.Launcher.ALL_APPS_WORK_TAB;
-import static android.app.admin.DevicePolicyResources.Strings.Launcher.ALL_APPS_WORK_TAB_ACCESSIBILITY;
-import static android.app.admin.DevicePolicyResources.Strings.Launcher.DISABLED_BY_ADMIN_MESSAGE;
-import static android.app.admin.DevicePolicyResources.Strings.Launcher.WIDGETS_PERSONAL_TAB;
-import static android.app.admin.DevicePolicyResources.Strings.Launcher.WIDGETS_WORK_TAB;
-import static android.app.admin.DevicePolicyResources.Strings.Launcher.WORK_FOLDER_NAME;
-import static android.app.admin.DevicePolicyResources.Strings.Launcher.WORK_PROFILE_EDU;
-import static android.app.admin.DevicePolicyResources.Strings.Launcher.WORK_PROFILE_EDU_ACCEPT;
-import static android.app.admin.DevicePolicyResources.Strings.Launcher.WORK_PROFILE_ENABLE_BUTTON;
-import static android.app.admin.DevicePolicyResources.Strings.Launcher.WORK_PROFILE_PAUSED_DESCRIPTION;
-import static android.app.admin.DevicePolicyResources.Strings.Launcher.WORK_PROFILE_PAUSE_BUTTON;
-import static android.app.admin.DevicePolicyResources.Strings.MediaProvider.BLOCKED_BY_ADMIN_TITLE;
-import static android.app.admin.DevicePolicyResources.Strings.MediaProvider.BLOCKED_FROM_PERSONAL_MESSAGE;
-import static android.app.admin.DevicePolicyResources.Strings.MediaProvider.BLOCKED_FROM_WORK_MESSAGE;
-import static android.app.admin.DevicePolicyResources.Strings.MediaProvider.SWITCH_TO_PERSONAL_MESSAGE;
-import static android.app.admin.DevicePolicyResources.Strings.MediaProvider.SWITCH_TO_WORK_MESSAGE;
-import static android.app.admin.DevicePolicyResources.Strings.MediaProvider.WORK_PROFILE_PAUSED_MESSAGE;
-import static android.app.admin.DevicePolicyResources.Strings.PermissionController.BACKGROUND_ACCESS_DISABLED_BY_ADMIN_MESSAGE;
-import static android.app.admin.DevicePolicyResources.Strings.PermissionController.BACKGROUND_ACCESS_ENABLED_BY_ADMIN_MESSAGE;
-import static android.app.admin.DevicePolicyResources.Strings.PermissionController.FOREGROUND_ACCESS_ENABLED_BY_ADMIN_MESSAGE;
-import static android.app.admin.DevicePolicyResources.Strings.PermissionController.HOME_MISSING_WORK_PROFILE_SUPPORT_MESSAGE;
-import static android.app.admin.DevicePolicyResources.Strings.PermissionController.LOCATION_AUTO_GRANTED_MESSAGE;
-import static android.app.admin.DevicePolicyResources.Strings.PermissionController.WORK_PROFILE_DEFAULT_APPS_TITLE;
-import static android.app.admin.DevicePolicyResources.Strings.Settings.ACCESSIBILITY_CATEGORY_PERSONAL;
-import static android.app.admin.DevicePolicyResources.Strings.Settings.ACCESSIBILITY_CATEGORY_WORK;
-import static android.app.admin.DevicePolicyResources.Strings.Settings.ACCESSIBILITY_PERSONAL_ACCOUNT_TITLE;
-import static android.app.admin.DevicePolicyResources.Strings.Settings.ACCESSIBILITY_WORK_ACCOUNT_TITLE;
-import static android.app.admin.DevicePolicyResources.Strings.Settings.ACCOUNTS_SEARCH_KEYWORDS;
-import static android.app.admin.DevicePolicyResources.Strings.Settings.ACTIVATE_DEVICE_ADMIN_APP;
-import static android.app.admin.DevicePolicyResources.Strings.Settings.ACTIVATE_DEVICE_ADMIN_APP_TITLE;
-import static android.app.admin.DevicePolicyResources.Strings.Settings.ACTIVATE_THIS_DEVICE_ADMIN_APP;
-import static android.app.admin.DevicePolicyResources.Strings.Settings.ACTIVE_DEVICE_ADMIN_WARNING;
-import static android.app.admin.DevicePolicyResources.Strings.Settings.ADMIN_ACTIONS_APPS_COUNT;
-import static android.app.admin.DevicePolicyResources.Strings.Settings.ADMIN_ACTIONS_APPS_COUNT_MINIMUM;
-import static android.app.admin.DevicePolicyResources.Strings.Settings.ADMIN_ACTION_ACCESS_CAMERA;
-import static android.app.admin.DevicePolicyResources.Strings.Settings.ADMIN_ACTION_ACCESS_LOCATION;
-import static android.app.admin.DevicePolicyResources.Strings.Settings.ADMIN_ACTION_ACCESS_MICROPHONE;
-import static android.app.admin.DevicePolicyResources.Strings.Settings.ADMIN_ACTION_APPS_COUNT_ESTIMATED;
-import static android.app.admin.DevicePolicyResources.Strings.Settings.ADMIN_ACTION_APPS_INSTALLED;
-import static android.app.admin.DevicePolicyResources.Strings.Settings.ADMIN_ACTION_NONE;
-import static android.app.admin.DevicePolicyResources.Strings.Settings.ADMIN_ACTION_SET_CURRENT_INPUT_METHOD;
-import static android.app.admin.DevicePolicyResources.Strings.Settings.ADMIN_ACTION_SET_DEFAULT_APPS;
-import static android.app.admin.DevicePolicyResources.Strings.Settings.ADMIN_ACTION_SET_HTTP_PROXY;
-import static android.app.admin.DevicePolicyResources.Strings.Settings.ADMIN_ACTION_SET_INPUT_METHOD_NAME;
-import static android.app.admin.DevicePolicyResources.Strings.Settings.ADMIN_CAN_LOCK_DEVICE;
-import static android.app.admin.DevicePolicyResources.Strings.Settings.ADMIN_CAN_SEE_APPS_WARNING;
-import static android.app.admin.DevicePolicyResources.Strings.Settings.ADMIN_CAN_SEE_BUG_REPORT_WARNING;
-import static android.app.admin.DevicePolicyResources.Strings.Settings.ADMIN_CAN_SEE_NETWORK_LOGS_WARNING;
-import static android.app.admin.DevicePolicyResources.Strings.Settings.ADMIN_CAN_SEE_SECURITY_LOGS_WARNING;
-import static android.app.admin.DevicePolicyResources.Strings.Settings.ADMIN_CAN_SEE_USAGE_WARNING;
-import static android.app.admin.DevicePolicyResources.Strings.Settings.ADMIN_CAN_SEE_WORK_DATA_WARNING;
-import static android.app.admin.DevicePolicyResources.Strings.Settings.ADMIN_CAN_WIPE_DEVICE;
-import static android.app.admin.DevicePolicyResources.Strings.Settings.ADMIN_CONFIGURED_FAILED_PASSWORD_WIPE_DEVICE;
-import static android.app.admin.DevicePolicyResources.Strings.Settings.ADMIN_CONFIGURED_FAILED_PASSWORD_WIPE_WORK_PROFILE;
-import static android.app.admin.DevicePolicyResources.Strings.Settings.ALWAYS_ON_VPN_DEVICE;
-import static android.app.admin.DevicePolicyResources.Strings.Settings.ALWAYS_ON_VPN_PERSONAL_PROFILE;
-import static android.app.admin.DevicePolicyResources.Strings.Settings.ALWAYS_ON_VPN_WORK_PROFILE;
-import static android.app.admin.DevicePolicyResources.Strings.Settings.APP_CAN_ACCESS_PERSONAL_DATA;
-import static android.app.admin.DevicePolicyResources.Strings.Settings.APP_CAN_ACCESS_PERSONAL_PERMISSIONS;
-import static android.app.admin.DevicePolicyResources.Strings.Settings.CA_CERTS_DEVICE;
-import static android.app.admin.DevicePolicyResources.Strings.Settings.CA_CERTS_PERSONAL_PROFILE;
-import static android.app.admin.DevicePolicyResources.Strings.Settings.CA_CERTS_WORK_PROFILE;
-import static android.app.admin.DevicePolicyResources.Strings.Settings.CHANGES_MADE_BY_YOUR_ORGANIZATION_ADMIN_TITLE;
-import static android.app.admin.DevicePolicyResources.Strings.Settings.CONFIRM_WORK_PROFILE_PASSWORD_HEADER;
-import static android.app.admin.DevicePolicyResources.Strings.Settings.CONFIRM_WORK_PROFILE_PATTERN_HEADER;
-import static android.app.admin.DevicePolicyResources.Strings.Settings.CONFIRM_WORK_PROFILE_PIN_HEADER;
-import static android.app.admin.DevicePolicyResources.Strings.Settings.CONNECTED_APPS_SEARCH_KEYWORDS;
-import static android.app.admin.DevicePolicyResources.Strings.Settings.CONNECTED_APPS_SHARE_PERMISSIONS_AND_DATA;
-import static android.app.admin.DevicePolicyResources.Strings.Settings.CONNECTED_WORK_AND_PERSONAL_APPS_TITLE;
-import static android.app.admin.DevicePolicyResources.Strings.Settings.CONNECT_APPS_DIALOG_SUMMARY;
-import static android.app.admin.DevicePolicyResources.Strings.Settings.CONNECT_APPS_DIALOG_TITLE;
-import static android.app.admin.DevicePolicyResources.Strings.Settings.CONTACT_YOUR_IT_ADMIN;
-import static android.app.admin.DevicePolicyResources.Strings.Settings.CONTROLLED_BY_ADMIN_SUMMARY;
-import static android.app.admin.DevicePolicyResources.Strings.Settings.CROSS_PROFILE_CALENDAR_SUMMARY;
-import static android.app.admin.DevicePolicyResources.Strings.Settings.CROSS_PROFILE_CALENDAR_TITLE;
-import static android.app.admin.DevicePolicyResources.Strings.Settings.DEVICE_ADMIN_POLICIES_WARNING;
-import static android.app.admin.DevicePolicyResources.Strings.Settings.DEVICE_ADMIN_SETTINGS_TITLE;
-import static android.app.admin.DevicePolicyResources.Strings.Settings.DEVICE_MANAGED_WITHOUT_NAME;
-import static android.app.admin.DevicePolicyResources.Strings.Settings.DEVICE_MANAGED_WITH_NAME;
-import static android.app.admin.DevicePolicyResources.Strings.Settings.DEVICE_OWNER_INSTALLED_CERTIFICATE_AUTHORITY_WARNING;
-import static android.app.admin.DevicePolicyResources.Strings.Settings.DISABLED_BY_IT_ADMIN_TITLE;
-import static android.app.admin.DevicePolicyResources.Strings.Settings.ENABLE_WORK_PROFILE_SYNC_WITH_PERSONAL_SOUNDS_DIALOG_MESSAGE;
-import static android.app.admin.DevicePolicyResources.Strings.Settings.ENABLE_WORK_PROFILE_SYNC_WITH_PERSONAL_SOUNDS_DIALOG_TITLE;
-import static android.app.admin.DevicePolicyResources.Strings.Settings.ENTERPRISE_PRIVACY_HEADER;
-import static android.app.admin.DevicePolicyResources.Strings.Settings.ERROR_MOVE_DEVICE_ADMIN;
-import static android.app.admin.DevicePolicyResources.Strings.Settings.FACE_SETTINGS_FOR_WORK_TITLE;
-import static android.app.admin.DevicePolicyResources.Strings.Settings.FACE_UNLOCK_DISABLED;
-import static android.app.admin.DevicePolicyResources.Strings.Settings.FINGERPRINT_FOR_WORK;
-import static android.app.admin.DevicePolicyResources.Strings.Settings.FINGERPRINT_UNLOCK_DISABLED;
-import static android.app.admin.DevicePolicyResources.Strings.Settings.FINGERPRINT_UNLOCK_DISABLED_EXPLANATION;
-import static android.app.admin.DevicePolicyResources.Strings.Settings.FORGOT_PASSWORD_TEXT;
-import static android.app.admin.DevicePolicyResources.Strings.Settings.FORGOT_PASSWORD_TITLE;
-import static android.app.admin.DevicePolicyResources.Strings.Settings.HOW_TO_DISCONNECT_APPS;
-import static android.app.admin.DevicePolicyResources.Strings.Settings.INFORMATION_YOUR_ORGANIZATION_CAN_SEE_TITLE;
-import static android.app.admin.DevicePolicyResources.Strings.Settings.INSTALL_IN_PERSONAL_PROFILE_TO_CONNECT_PROMPT;
-import static android.app.admin.DevicePolicyResources.Strings.Settings.INSTALL_IN_WORK_PROFILE_TO_CONNECT_PROMPT;
-import static android.app.admin.DevicePolicyResources.Strings.Settings.IT_ADMIN_POLICY_DISABLING_INFO_URL;
-import static android.app.admin.DevicePolicyResources.Strings.Settings.MANAGED_BY;
-import static android.app.admin.DevicePolicyResources.Strings.Settings.MANAGED_DEVICE_INFO;
-import static android.app.admin.DevicePolicyResources.Strings.Settings.MANAGED_DEVICE_INFO_SUMMARY;
-import static android.app.admin.DevicePolicyResources.Strings.Settings.MANAGED_DEVICE_INFO_SUMMARY_WITH_NAME;
-import static android.app.admin.DevicePolicyResources.Strings.Settings.MANAGED_PROFILE_SETTINGS_TITLE;
-import static android.app.admin.DevicePolicyResources.Strings.Settings.MANAGE_DEVICE_ADMIN_APPS;
-import static android.app.admin.DevicePolicyResources.Strings.Settings.NEW_DEVICE_ADMIN_WARNING;
-import static android.app.admin.DevicePolicyResources.Strings.Settings.NEW_DEVICE_ADMIN_WARNING_SIMPLIFIED;
-import static android.app.admin.DevicePolicyResources.Strings.Settings.NO_DEVICE_ADMINS;
-import static android.app.admin.DevicePolicyResources.Strings.Settings.NUMBER_OF_DEVICE_ADMINS;
-import static android.app.admin.DevicePolicyResources.Strings.Settings.NUMBER_OF_DEVICE_ADMINS_NONE;
-import static android.app.admin.DevicePolicyResources.Strings.Settings.ONLY_CONNECT_TRUSTED_APPS;
-import static android.app.admin.DevicePolicyResources.Strings.Settings.OTHER_OPTIONS_DISABLED_BY_ADMIN;
-import static android.app.admin.DevicePolicyResources.Strings.Settings.PASSWORD_RECENTLY_USED;
-import static android.app.admin.DevicePolicyResources.Strings.Settings.PERSONAL_CATEGORY_HEADER;
-import static android.app.admin.DevicePolicyResources.Strings.Settings.PERSONAL_PROFILE_APP_SUBTEXT;
-import static android.app.admin.DevicePolicyResources.Strings.Settings.PIN_RECENTLY_USED;
-import static android.app.admin.DevicePolicyResources.Strings.Settings.REENTER_WORK_PROFILE_PASSWORD_HEADER;
-import static android.app.admin.DevicePolicyResources.Strings.Settings.REENTER_WORK_PROFILE_PIN_HEADER;
-import static android.app.admin.DevicePolicyResources.Strings.Settings.REMOVE_ACCOUNT_FAILED_ADMIN_RESTRICTION;
-import static android.app.admin.DevicePolicyResources.Strings.Settings.REMOVE_AND_UNINSTALL_DEVICE_ADMIN;
-import static android.app.admin.DevicePolicyResources.Strings.Settings.REMOVE_DEVICE_ADMIN;
-import static android.app.admin.DevicePolicyResources.Strings.Settings.REMOVE_WORK_PROFILE;
-import static android.app.admin.DevicePolicyResources.Strings.Settings.SELECT_DEVICE_ADMIN_APPS;
-import static android.app.admin.DevicePolicyResources.Strings.Settings.SET_PROFILE_OWNER_DIALOG_TITLE;
-import static android.app.admin.DevicePolicyResources.Strings.Settings.SET_PROFILE_OWNER_POSTSETUP_WARNING;
-import static android.app.admin.DevicePolicyResources.Strings.Settings.SET_PROFILE_OWNER_TITLE;
-import static android.app.admin.DevicePolicyResources.Strings.Settings.SET_WORK_PROFILE_PASSWORD_HEADER;
-import static android.app.admin.DevicePolicyResources.Strings.Settings.SET_WORK_PROFILE_PATTERN_HEADER;
-import static android.app.admin.DevicePolicyResources.Strings.Settings.SET_WORK_PROFILE_PIN_HEADER;
-import static android.app.admin.DevicePolicyResources.Strings.Settings.SHARE_REMOTE_BUGREPORT_DIALOG_TITLE;
-import static android.app.admin.DevicePolicyResources.Strings.Settings.SHARE_REMOTE_BUGREPORT_FINISHED_REQUEST_CONSENT;
-import static android.app.admin.DevicePolicyResources.Strings.Settings.SHARE_REMOTE_BUGREPORT_NOT_FINISHED_REQUEST_CONSENT;
-import static android.app.admin.DevicePolicyResources.Strings.Settings.SHARING_REMOTE_BUGREPORT_MESSAGE;
-import static android.app.admin.DevicePolicyResources.Strings.Settings.UNINSTALL_DEVICE_ADMIN;
-import static android.app.admin.DevicePolicyResources.Strings.Settings.USER_ADMIN_POLICIES_WARNING;
-import static android.app.admin.DevicePolicyResources.Strings.Settings.WORK_APPS_CANNOT_ACCESS_NOTIFICATION_SETTINGS;
-import static android.app.admin.DevicePolicyResources.Strings.Settings.WORK_CATEGORY_HEADER;
-import static android.app.admin.DevicePolicyResources.Strings.Settings.WORK_PROFILE_ADMIN_POLICIES_WARNING;
-import static android.app.admin.DevicePolicyResources.Strings.Settings.WORK_PROFILE_ALARM_RINGTONE_TITLE;
-import static android.app.admin.DevicePolicyResources.Strings.Settings.WORK_PROFILE_APP_SUBTEXT;
-import static android.app.admin.DevicePolicyResources.Strings.Settings.WORK_PROFILE_CONFIRM_PATTERN;
-import static android.app.admin.DevicePolicyResources.Strings.Settings.WORK_PROFILE_CONFIRM_PIN;
-import static android.app.admin.DevicePolicyResources.Strings.Settings.WORK_PROFILE_CONFIRM_REMOVE_MESSAGE;
-import static android.app.admin.DevicePolicyResources.Strings.Settings.WORK_PROFILE_CONFIRM_REMOVE_TITLE;
-import static android.app.admin.DevicePolicyResources.Strings.Settings.WORK_PROFILE_CONTACT_SEARCH_SUMMARY;
-import static android.app.admin.DevicePolicyResources.Strings.Settings.WORK_PROFILE_CONTACT_SEARCH_TITLE;
-import static android.app.admin.DevicePolicyResources.Strings.Settings.WORK_PROFILE_DISABLE_USAGE_ACCESS_WARNING;
-import static android.app.admin.DevicePolicyResources.Strings.Settings.WORK_PROFILE_FINGERPRINT_LAST_DELETE_MESSAGE;
-import static android.app.admin.DevicePolicyResources.Strings.Settings.WORK_PROFILE_INSTALLED_CERTIFICATE_AUTHORITY_WARNING;
-import static android.app.admin.DevicePolicyResources.Strings.Settings.WORK_PROFILE_IT_ADMIN_CANT_RESET_SCREEN_LOCK;
-import static android.app.admin.DevicePolicyResources.Strings.Settings.WORK_PROFILE_KEYBOARDS_AND_TOOLS;
-import static android.app.admin.DevicePolicyResources.Strings.Settings.WORK_PROFILE_LAST_PASSWORD_ATTEMPT_BEFORE_WIPE;
-import static android.app.admin.DevicePolicyResources.Strings.Settings.WORK_PROFILE_LAST_PATTERN_ATTEMPT_BEFORE_WIPE;
-import static android.app.admin.DevicePolicyResources.Strings.Settings.WORK_PROFILE_LAST_PIN_ATTEMPT_BEFORE_WIPE;
-import static android.app.admin.DevicePolicyResources.Strings.Settings.WORK_PROFILE_LOCATION_SWITCH_TITLE;
-import static android.app.admin.DevicePolicyResources.Strings.Settings.WORK_PROFILE_LOCKED_NOTIFICATION_TITLE;
-import static android.app.admin.DevicePolicyResources.Strings.Settings.WORK_PROFILE_LOCK_ATTEMPTS_FAILED;
-import static android.app.admin.DevicePolicyResources.Strings.Settings.WORK_PROFILE_LOCK_SCREEN_REDACT_NOTIFICATION_SUMMARY;
-import static android.app.admin.DevicePolicyResources.Strings.Settings.WORK_PROFILE_LOCK_SCREEN_REDACT_NOTIFICATION_TITLE;
-import static android.app.admin.DevicePolicyResources.Strings.Settings.WORK_PROFILE_MANAGED_BY;
-import static android.app.admin.DevicePolicyResources.Strings.Settings.WORK_PROFILE_NOTIFICATIONS_SECTION_HEADER;
-import static android.app.admin.DevicePolicyResources.Strings.Settings.WORK_PROFILE_NOTIFICATION_LISTENER_BLOCKED;
-import static android.app.admin.DevicePolicyResources.Strings.Settings.WORK_PROFILE_NOTIFICATION_RINGTONE_TITLE;
-import static android.app.admin.DevicePolicyResources.Strings.Settings.WORK_PROFILE_NOT_AVAILABLE;
-import static android.app.admin.DevicePolicyResources.Strings.Settings.WORK_PROFILE_OFF_CONDITION_TITLE;
-import static android.app.admin.DevicePolicyResources.Strings.Settings.WORK_PROFILE_PASSWORD_REQUIRED;
-import static android.app.admin.DevicePolicyResources.Strings.Settings.WORK_PROFILE_PRIVACY_POLICY_INFO;
-import static android.app.admin.DevicePolicyResources.Strings.Settings.WORK_PROFILE_PRIVACY_POLICY_INFO_SUMMARY;
-import static android.app.admin.DevicePolicyResources.Strings.Settings.WORK_PROFILE_RINGTONE_TITLE;
-import static android.app.admin.DevicePolicyResources.Strings.Settings.WORK_PROFILE_SCREEN_LOCK_SETUP_MESSAGE;
-import static android.app.admin.DevicePolicyResources.Strings.Settings.WORK_PROFILE_SECURITY_TITLE;
-import static android.app.admin.DevicePolicyResources.Strings.Settings.WORK_PROFILE_SETTING;
-import static android.app.admin.DevicePolicyResources.Strings.Settings.WORK_PROFILE_SETTING_OFF_SUMMARY;
-import static android.app.admin.DevicePolicyResources.Strings.Settings.WORK_PROFILE_SETTING_ON_SUMMARY;
-import static android.app.admin.DevicePolicyResources.Strings.Settings.WORK_PROFILE_SET_UNLOCK_LAUNCH_PICKER_TITLE;
-import static android.app.admin.DevicePolicyResources.Strings.Settings.WORK_PROFILE_SOUND_SETTINGS_SECTION_HEADER;
-import static android.app.admin.DevicePolicyResources.Strings.Settings.WORK_PROFILE_SYNC_WITH_PERSONAL_SOUNDS_ACTIVE_SUMMARY;
-import static android.app.admin.DevicePolicyResources.Strings.Settings.WORK_PROFILE_UNIFICATION_SEARCH_KEYWORDS;
-import static android.app.admin.DevicePolicyResources.Strings.Settings.WORK_PROFILE_UNIFY_LOCKS_DETAIL;
-import static android.app.admin.DevicePolicyResources.Strings.Settings.WORK_PROFILE_UNIFY_LOCKS_NONCOMPLIANT;
-import static android.app.admin.DevicePolicyResources.Strings.Settings.WORK_PROFILE_UNIFY_LOCKS_SUMMARY;
-import static android.app.admin.DevicePolicyResources.Strings.Settings.WORK_PROFILE_UNIFY_LOCKS_TITLE;
-import static android.app.admin.DevicePolicyResources.Strings.Settings.WORK_PROFILE_USER_LABEL;
-import static android.app.admin.DevicePolicyResources.Strings.Settings.WORK_PROFILE_USE_PERSONAL_SOUNDS_SUMMARY;
-import static android.app.admin.DevicePolicyResources.Strings.Settings.WORK_PROFILE_USE_PERSONAL_SOUNDS_TITLE;
-import static android.app.admin.DevicePolicyResources.Strings.Settings.YOUR_ACCESS_TO_THIS_DEVICE_TITLE;
-import static android.app.admin.DevicePolicyResources.Strings.SystemUi.BIOMETRIC_DIALOG_WORK_LOCK_FAILED_ATTEMPTS;
-import static android.app.admin.DevicePolicyResources.Strings.SystemUi.BIOMETRIC_DIALOG_WORK_PASSWORD_LAST_ATTEMPT;
-import static android.app.admin.DevicePolicyResources.Strings.SystemUi.BIOMETRIC_DIALOG_WORK_PATTERN_LAST_ATTEMPT;
-import static android.app.admin.DevicePolicyResources.Strings.SystemUi.BIOMETRIC_DIALOG_WORK_PIN_LAST_ATTEMPT;
-import static android.app.admin.DevicePolicyResources.Strings.SystemUi.KEYGUARD_MANAGEMENT_DISCLOSURE;
-import static android.app.admin.DevicePolicyResources.Strings.SystemUi.KEYGUARD_NAMED_MANAGEMENT_DISCLOSURE;
-import static android.app.admin.DevicePolicyResources.Strings.SystemUi.ONGOING_PRIVACY_DIALOG_WORK;
-import static android.app.admin.DevicePolicyResources.Strings.SystemUi.QS_DIALOG_MANAGEMENT;
-import static android.app.admin.DevicePolicyResources.Strings.SystemUi.QS_DIALOG_MANAGEMENT_CA_CERT;
-import static android.app.admin.DevicePolicyResources.Strings.SystemUi.QS_DIALOG_MANAGEMENT_NAMED_VPN;
-import static android.app.admin.DevicePolicyResources.Strings.SystemUi.QS_DIALOG_MANAGEMENT_NETWORK;
-import static android.app.admin.DevicePolicyResources.Strings.SystemUi.QS_DIALOG_MANAGEMENT_TITLE;
-import static android.app.admin.DevicePolicyResources.Strings.SystemUi.QS_DIALOG_MANAGEMENT_TWO_NAMED_VPN;
-import static android.app.admin.DevicePolicyResources.Strings.SystemUi.QS_DIALOG_NAMED_MANAGEMENT;
-import static android.app.admin.DevicePolicyResources.Strings.SystemUi.QS_DIALOG_PERSONAL_PROFILE_NAMED_VPN;
-import static android.app.admin.DevicePolicyResources.Strings.SystemUi.QS_DIALOG_VIEW_POLICIES;
-import static android.app.admin.DevicePolicyResources.Strings.SystemUi.QS_DIALOG_WORK_PROFILE_CA_CERT;
-import static android.app.admin.DevicePolicyResources.Strings.SystemUi.QS_DIALOG_WORK_PROFILE_NAMED_VPN;
-import static android.app.admin.DevicePolicyResources.Strings.SystemUi.QS_DIALOG_WORK_PROFILE_NETWORK;
-import static android.app.admin.DevicePolicyResources.Strings.SystemUi.QS_MSG_MANAGEMENT;
-import static android.app.admin.DevicePolicyResources.Strings.SystemUi.QS_MSG_MANAGEMENT_MONITORING;
-import static android.app.admin.DevicePolicyResources.Strings.SystemUi.QS_MSG_MANAGEMENT_MULTIPLE_VPNS;
-import static android.app.admin.DevicePolicyResources.Strings.SystemUi.QS_MSG_MANAGEMENT_NAMED_VPN;
-import static android.app.admin.DevicePolicyResources.Strings.SystemUi.QS_MSG_NAMED_MANAGEMENT;
-import static android.app.admin.DevicePolicyResources.Strings.SystemUi.QS_MSG_NAMED_MANAGEMENT_MONITORING;
-import static android.app.admin.DevicePolicyResources.Strings.SystemUi.QS_MSG_NAMED_MANAGEMENT_MULTIPLE_VPNS;
-import static android.app.admin.DevicePolicyResources.Strings.SystemUi.QS_MSG_NAMED_MANAGEMENT_NAMED_VPN;
-import static android.app.admin.DevicePolicyResources.Strings.SystemUi.QS_MSG_NAMED_WORK_PROFILE_MONITORING;
-import static android.app.admin.DevicePolicyResources.Strings.SystemUi.QS_MSG_PERSONAL_PROFILE_NAMED_VPN;
-import static android.app.admin.DevicePolicyResources.Strings.SystemUi.QS_MSG_WORK_PROFILE_MONITORING;
-import static android.app.admin.DevicePolicyResources.Strings.SystemUi.QS_MSG_WORK_PROFILE_NAMED_VPN;
-import static android.app.admin.DevicePolicyResources.Strings.SystemUi.QS_MSG_WORK_PROFILE_NETWORK;
-import static android.app.admin.DevicePolicyResources.Strings.SystemUi.STATUS_BAR_WORK_ICON_ACCESSIBILITY;
-import static android.app.admin.DevicePolicyResources.Strings.SystemUi.WORK_LOCK_ACCESSIBILITY;
-
-import android.annotation.StringDef;
-import android.annotation.SuppressLint;
import android.annotation.SystemApi;
import android.os.UserHandle;
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import java.util.HashSet;
-import java.util.Set;
-
/**
* Class containing the required identifiers to update device management resources.
*
- * <p>See {@link DevicePolicyManager#getDrawable} and
- * {@code DevicePolicyManager#getString}.
+ * <p>See {@link DevicePolicyResourcesManager#getDrawable} and
+ * {@link DevicePolicyResourcesManager#getString}.
*/
public final class DevicePolicyResources {
private DevicePolicyResources() {}
/**
- * Resource identifiers used to update device management-related system drawable resources.
- *
- * @hide
+ * An identifier used for:
+ * <ul>
+ * <li>un-updatable resource IDs</li>
+ * <li>undefined sources</li>
+ * </ul>
*/
- @Retention(RetentionPolicy.SOURCE)
- @StringDef(value = {
- Drawables.UNDEFINED,
- Drawables.WORK_PROFILE_ICON_BADGE,
- Drawables.WORK_PROFILE_ICON,
- Drawables.WORK_PROFILE_OFF_ICON,
- Drawables.WORK_PROFILE_USER_ICON
- })
- public @interface UpdatableDrawableId {
- }
-
- /**
- * Identifiers to specify the desired style for the updatable device management system
- * resource.
- *
- * @hide
- */
- @Retention(RetentionPolicy.SOURCE)
- @StringDef(value = {
- Drawables.Style.SOLID_COLORED,
- Drawables.Style.SOLID_NOT_COLORED,
- Drawables.Style.OUTLINE,
- Drawables.Style.DEFAULT
- })
- public @interface UpdatableDrawableStyle {
- }
-
- /**
- * Identifiers to specify the location if the updatable device management system resource.
- *
- * @hide
- */
- @Retention(RetentionPolicy.SOURCE)
- @StringDef(value = {
- Drawables.Source.UNDEFINED,
- Drawables.Source.NOTIFICATION,
- Drawables.Source.PROFILE_SWITCH_ANIMATION,
- Drawables.Source.HOME_WIDGET,
- Drawables.Source.LAUNCHER_OFF_BUTTON,
- Drawables.Source.QUICK_SETTINGS,
- Drawables.Source.STATUS_BAR
- })
- public @interface UpdatableDrawableSource {
- }
-
- /**
- * Resource identifiers used to update device management-related string resources.
- *
- * @hide
- */
- @Retention(RetentionPolicy.SOURCE)
- @StringDef({
- // Launcher Strings
- WORK_PROFILE_EDU, WORK_PROFILE_EDU_ACCEPT, Strings.Launcher.WORK_PROFILE_PAUSED_TITLE,
- WORK_PROFILE_PAUSED_DESCRIPTION, WORK_PROFILE_PAUSE_BUTTON, WORK_PROFILE_ENABLE_BUTTON,
- ALL_APPS_WORK_TAB, ALL_APPS_PERSONAL_TAB, ALL_APPS_WORK_TAB_ACCESSIBILITY,
- ALL_APPS_PERSONAL_TAB_ACCESSIBILITY, WORK_FOLDER_NAME, WIDGETS_WORK_TAB,
- WIDGETS_PERSONAL_TAB, DISABLED_BY_ADMIN_MESSAGE,
-
- // SysUI Strings
- QS_MSG_MANAGEMENT, QS_MSG_NAMED_MANAGEMENT, QS_MSG_MANAGEMENT_MONITORING,
- QS_MSG_NAMED_MANAGEMENT_MONITORING, QS_MSG_MANAGEMENT_NAMED_VPN,
- QS_MSG_NAMED_MANAGEMENT_NAMED_VPN, QS_MSG_MANAGEMENT_MULTIPLE_VPNS,
- QS_MSG_NAMED_MANAGEMENT_MULTIPLE_VPNS, QS_MSG_WORK_PROFILE_MONITORING,
- QS_MSG_NAMED_WORK_PROFILE_MONITORING, QS_MSG_WORK_PROFILE_NETWORK,
- QS_MSG_WORK_PROFILE_NAMED_VPN, QS_MSG_PERSONAL_PROFILE_NAMED_VPN,
- QS_DIALOG_MANAGEMENT_TITLE, QS_DIALOG_VIEW_POLICIES, QS_DIALOG_MANAGEMENT,
- QS_DIALOG_NAMED_MANAGEMENT, QS_DIALOG_MANAGEMENT_CA_CERT,
- QS_DIALOG_WORK_PROFILE_CA_CERT, QS_DIALOG_MANAGEMENT_NETWORK,
- QS_DIALOG_WORK_PROFILE_NETWORK, QS_DIALOG_MANAGEMENT_NAMED_VPN,
- QS_DIALOG_MANAGEMENT_TWO_NAMED_VPN, QS_DIALOG_WORK_PROFILE_NAMED_VPN,
- QS_DIALOG_PERSONAL_PROFILE_NAMED_VPN, BIOMETRIC_DIALOG_WORK_PIN_LAST_ATTEMPT,
- BIOMETRIC_DIALOG_WORK_PATTERN_LAST_ATTEMPT, BIOMETRIC_DIALOG_WORK_PASSWORD_LAST_ATTEMPT,
- BIOMETRIC_DIALOG_WORK_LOCK_FAILED_ATTEMPTS, STATUS_BAR_WORK_ICON_ACCESSIBILITY,
- ONGOING_PRIVACY_DIALOG_WORK, KEYGUARD_MANAGEMENT_DISCLOSURE,
- KEYGUARD_NAMED_MANAGEMENT_DISCLOSURE, WORK_LOCK_ACCESSIBILITY,
-
- // Core Strings
- WORK_PROFILE_DELETED_TITLE, WORK_PROFILE_DELETED_FAILED_PASSWORD_ATTEMPTS_MESSAGE,
- WORK_PROFILE_DELETED_GENERIC_MESSAGE, WORK_PROFILE_DELETED_ORG_OWNED_MESSAGE,
- PERSONAL_APP_SUSPENSION_TITLE, PERSONAL_APP_SUSPENSION_MESSAGE,
- PERSONAL_APP_SUSPENSION_SOON_MESSAGE, PERSONAL_APP_SUSPENSION_TURN_ON_PROFILE,
- PRINTING_DISABLED_NAMED_ADMIN, LOCATION_CHANGED_TITLE, LOCATION_CHANGED_MESSAGE,
- NETWORK_LOGGING_TITLE, NETWORK_LOGGING_MESSAGE,
- NOTIFICATION_WORK_PROFILE_CONTENT_DESCRIPTION, NOTIFICATION_CHANNEL_DEVICE_ADMIN,
- SWITCH_TO_WORK_LABEL, SWITCH_TO_PERSONAL_LABEL, FORWARD_INTENT_TO_WORK,
- FORWARD_INTENT_TO_PERSONAL, RESOLVER_WORK_PROFILE_NOT_SUPPORTED, RESOLVER_PERSONAL_TAB,
- RESOLVER_WORK_TAB, RESOLVER_PERSONAL_TAB_ACCESSIBILITY, RESOLVER_WORK_TAB_ACCESSIBILITY,
- RESOLVER_CROSS_PROFILE_BLOCKED_TITLE, RESOLVER_CANT_SHARE_WITH_PERSONAL,
- RESOLVER_CANT_SHARE_WITH_WORK, RESOLVER_CANT_ACCESS_PERSONAL, RESOLVER_CANT_ACCESS_WORK,
- RESOLVER_WORK_PAUSED_TITLE, RESOLVER_NO_WORK_APPS, RESOLVER_NO_PERSONAL_APPS,
- CANT_ADD_ACCOUNT_MESSAGE, PACKAGE_INSTALLED_BY_DO, PACKAGE_UPDATED_BY_DO,
- PACKAGE_DELETED_BY_DO, UNLAUNCHABLE_APP_WORK_PAUSED_TITLE,
- UNLAUNCHABLE_APP_WORK_PAUSED_MESSAGE, PROFILE_ENCRYPTED_TITLE, PROFILE_ENCRYPTED_DETAIL,
- PROFILE_ENCRYPTED_MESSAGE, WORK_PROFILE_BADGED_LABEL,
-
- // DocsUi Strings
- WORK_PROFILE_OFF_ERROR_TITLE, WORK_PROFILE_OFF_ENABLE_BUTTON,
- CANT_SELECT_WORK_FILES_TITLE, CANT_SELECT_WORK_FILES_MESSAGE,
- CANT_SELECT_PERSONAL_FILES_TITLE, CANT_SELECT_PERSONAL_FILES_MESSAGE,
- CANT_SAVE_TO_WORK_TITLE, CANT_SAVE_TO_WORK_MESSAGE, CANT_SAVE_TO_PERSONAL_TITLE,
- CANT_SAVE_TO_PERSONAL_MESSAGE, CROSS_PROFILE_NOT_ALLOWED_TITLE,
- CROSS_PROFILE_NOT_ALLOWED_MESSAGE, PREVIEW_WORK_FILE_ACCESSIBILITY, PERSONAL_TAB,
- WORK_TAB, WORK_ACCESSIBILITY,
-
- // MediaProvider Strings
- SWITCH_TO_WORK_MESSAGE, SWITCH_TO_PERSONAL_MESSAGE, BLOCKED_BY_ADMIN_TITLE,
- BLOCKED_FROM_PERSONAL_MESSAGE, BLOCKED_FROM_PERSONAL_MESSAGE,
- BLOCKED_FROM_WORK_MESSAGE, Strings.MediaProvider.WORK_PROFILE_PAUSED_TITLE,
- WORK_PROFILE_PAUSED_MESSAGE,
-
- // Settings Strings
- FACE_SETTINGS_FOR_WORK_TITLE, WORK_PROFILE_FINGERPRINT_LAST_DELETE_MESSAGE,
- WORK_PROFILE_IT_ADMIN_CANT_RESET_SCREEN_LOCK, WORK_PROFILE_SCREEN_LOCK_SETUP_MESSAGE,
- WORK_PROFILE_SET_UNLOCK_LAUNCH_PICKER_TITLE,
- WORK_PROFILE_LAST_PATTERN_ATTEMPT_BEFORE_WIPE,
- WORK_PROFILE_LAST_PIN_ATTEMPT_BEFORE_WIPE,
- WORK_PROFILE_LAST_PASSWORD_ATTEMPT_BEFORE_WIPE, WORK_PROFILE_LOCK_ATTEMPTS_FAILED,
- ACCESSIBILITY_CATEGORY_WORK, ACCESSIBILITY_CATEGORY_PERSONAL,
- ACCESSIBILITY_WORK_ACCOUNT_TITLE, ACCESSIBILITY_PERSONAL_ACCOUNT_TITLE,
- WORK_PROFILE_LOCATION_SWITCH_TITLE, SET_WORK_PROFILE_PASSWORD_HEADER,
- SET_WORK_PROFILE_PIN_HEADER, SET_WORK_PROFILE_PATTERN_HEADER,
- CONFIRM_WORK_PROFILE_PASSWORD_HEADER, CONFIRM_WORK_PROFILE_PIN_HEADER,
- CONFIRM_WORK_PROFILE_PATTERN_HEADER, REENTER_WORK_PROFILE_PASSWORD_HEADER,
- REENTER_WORK_PROFILE_PIN_HEADER, WORK_PROFILE_CONFIRM_PATTERN, WORK_PROFILE_CONFIRM_PIN,
- WORK_PROFILE_PASSWORD_REQUIRED, WORK_PROFILE_SECURITY_TITLE,
- WORK_PROFILE_UNIFY_LOCKS_TITLE, WORK_PROFILE_UNIFY_LOCKS_SUMMARY,
- WORK_PROFILE_UNIFY_LOCKS_DETAIL, WORK_PROFILE_UNIFY_LOCKS_NONCOMPLIANT,
- WORK_PROFILE_KEYBOARDS_AND_TOOLS, WORK_PROFILE_NOT_AVAILABLE, WORK_PROFILE_SETTING,
- WORK_PROFILE_SETTING_ON_SUMMARY, WORK_PROFILE_SETTING_OFF_SUMMARY, REMOVE_WORK_PROFILE,
- DEVICE_OWNER_INSTALLED_CERTIFICATE_AUTHORITY_WARNING,
- WORK_PROFILE_INSTALLED_CERTIFICATE_AUTHORITY_WARNING, WORK_PROFILE_CONFIRM_REMOVE_TITLE,
- WORK_PROFILE_CONFIRM_REMOVE_MESSAGE, WORK_APPS_CANNOT_ACCESS_NOTIFICATION_SETTINGS,
- WORK_PROFILE_SOUND_SETTINGS_SECTION_HEADER, WORK_PROFILE_USE_PERSONAL_SOUNDS_TITLE,
- WORK_PROFILE_USE_PERSONAL_SOUNDS_SUMMARY, WORK_PROFILE_RINGTONE_TITLE,
- WORK_PROFILE_NOTIFICATION_RINGTONE_TITLE, WORK_PROFILE_ALARM_RINGTONE_TITLE,
- WORK_PROFILE_SYNC_WITH_PERSONAL_SOUNDS_ACTIVE_SUMMARY,
- ENABLE_WORK_PROFILE_SYNC_WITH_PERSONAL_SOUNDS_DIALOG_TITLE,
- ENABLE_WORK_PROFILE_SYNC_WITH_PERSONAL_SOUNDS_DIALOG_MESSAGE,
- WORK_PROFILE_NOTIFICATIONS_SECTION_HEADER, WORK_PROFILE_LOCKED_NOTIFICATION_TITLE,
- WORK_PROFILE_LOCK_SCREEN_REDACT_NOTIFICATION_TITLE,
- WORK_PROFILE_LOCK_SCREEN_REDACT_NOTIFICATION_SUMMARY,
- WORK_PROFILE_NOTIFICATION_LISTENER_BLOCKED, CONNECTED_WORK_AND_PERSONAL_APPS_TITLE,
- CONNECTED_APPS_SHARE_PERMISSIONS_AND_DATA, ONLY_CONNECT_TRUSTED_APPS,
- HOW_TO_DISCONNECT_APPS, CONNECT_APPS_DIALOG_TITLE, CONNECT_APPS_DIALOG_SUMMARY,
- APP_CAN_ACCESS_PERSONAL_DATA, APP_CAN_ACCESS_PERSONAL_PERMISSIONS,
- INSTALL_IN_WORK_PROFILE_TO_CONNECT_PROMPT,
- INSTALL_IN_PERSONAL_PROFILE_TO_CONNECT_PROMPT, WORK_PROFILE_MANAGED_BY, MANAGED_BY,
- WORK_PROFILE_DISABLE_USAGE_ACCESS_WARNING, DISABLED_BY_IT_ADMIN_TITLE,
- CONTACT_YOUR_IT_ADMIN, WORK_PROFILE_ADMIN_POLICIES_WARNING, USER_ADMIN_POLICIES_WARNING,
- DEVICE_ADMIN_POLICIES_WARNING, WORK_PROFILE_OFF_CONDITION_TITLE,
- MANAGED_PROFILE_SETTINGS_TITLE, WORK_PROFILE_CONTACT_SEARCH_TITLE,
- WORK_PROFILE_CONTACT_SEARCH_SUMMARY, CROSS_PROFILE_CALENDAR_TITLE,
- CROSS_PROFILE_CALENDAR_SUMMARY, ALWAYS_ON_VPN_PERSONAL_PROFILE, ALWAYS_ON_VPN_DEVICE,
- ALWAYS_ON_VPN_WORK_PROFILE, CA_CERTS_PERSONAL_PROFILE, CA_CERTS_WORK_PROFILE,
- CA_CERTS_DEVICE, ADMIN_CAN_LOCK_DEVICE, ADMIN_CAN_WIPE_DEVICE,
- ADMIN_CONFIGURED_FAILED_PASSWORD_WIPE_DEVICE,
- ADMIN_CONFIGURED_FAILED_PASSWORD_WIPE_WORK_PROFILE, DEVICE_MANAGED_WITHOUT_NAME,
- DEVICE_MANAGED_WITH_NAME, WORK_PROFILE_APP_SUBTEXT, PERSONAL_PROFILE_APP_SUBTEXT,
- FINGERPRINT_FOR_WORK, FACE_UNLOCK_DISABLED, FINGERPRINT_UNLOCK_DISABLED,
- FINGERPRINT_UNLOCK_DISABLED_EXPLANATION, PIN_RECENTLY_USED, PASSWORD_RECENTLY_USED,
- MANAGE_DEVICE_ADMIN_APPS, NUMBER_OF_DEVICE_ADMINS_NONE, NUMBER_OF_DEVICE_ADMINS,
- FORGOT_PASSWORD_TITLE, FORGOT_PASSWORD_TEXT, ERROR_MOVE_DEVICE_ADMIN,
- DEVICE_ADMIN_SETTINGS_TITLE, REMOVE_DEVICE_ADMIN, UNINSTALL_DEVICE_ADMIN,
- REMOVE_AND_UNINSTALL_DEVICE_ADMIN, SELECT_DEVICE_ADMIN_APPS, NO_DEVICE_ADMINS,
- ACTIVATE_DEVICE_ADMIN_APP, ACTIVATE_THIS_DEVICE_ADMIN_APP,
- ACTIVATE_DEVICE_ADMIN_APP_TITLE, NEW_DEVICE_ADMIN_WARNING,
- NEW_DEVICE_ADMIN_WARNING_SIMPLIFIED, ACTIVE_DEVICE_ADMIN_WARNING,
- SET_PROFILE_OWNER_TITLE, SET_PROFILE_OWNER_DIALOG_TITLE,
- SET_PROFILE_OWNER_POSTSETUP_WARNING, OTHER_OPTIONS_DISABLED_BY_ADMIN,
- REMOVE_ACCOUNT_FAILED_ADMIN_RESTRICTION, IT_ADMIN_POLICY_DISABLING_INFO_URL,
- SHARE_REMOTE_BUGREPORT_DIALOG_TITLE, SHARE_REMOTE_BUGREPORT_FINISHED_REQUEST_CONSENT,
- SHARE_REMOTE_BUGREPORT_NOT_FINISHED_REQUEST_CONSENT, SHARING_REMOTE_BUGREPORT_MESSAGE,
- MANAGED_DEVICE_INFO, MANAGED_DEVICE_INFO_SUMMARY, MANAGED_DEVICE_INFO_SUMMARY_WITH_NAME,
- ENTERPRISE_PRIVACY_HEADER, INFORMATION_YOUR_ORGANIZATION_CAN_SEE_TITLE,
- CHANGES_MADE_BY_YOUR_ORGANIZATION_ADMIN_TITLE, YOUR_ACCESS_TO_THIS_DEVICE_TITLE,
- ADMIN_CAN_SEE_WORK_DATA_WARNING, ADMIN_CAN_SEE_APPS_WARNING,
- ADMIN_CAN_SEE_USAGE_WARNING, ADMIN_CAN_SEE_NETWORK_LOGS_WARNING,
- ADMIN_CAN_SEE_BUG_REPORT_WARNING, ADMIN_CAN_SEE_SECURITY_LOGS_WARNING,
- ADMIN_ACTION_NONE, ADMIN_ACTION_APPS_INSTALLED, ADMIN_ACTION_APPS_COUNT_ESTIMATED,
- ADMIN_ACTIONS_APPS_COUNT_MINIMUM, ADMIN_ACTION_ACCESS_LOCATION,
- ADMIN_ACTION_ACCESS_MICROPHONE, ADMIN_ACTION_ACCESS_CAMERA,
- ADMIN_ACTION_SET_DEFAULT_APPS, ADMIN_ACTIONS_APPS_COUNT,
- ADMIN_ACTION_SET_CURRENT_INPUT_METHOD, ADMIN_ACTION_SET_INPUT_METHOD_NAME,
- ADMIN_ACTION_SET_HTTP_PROXY, WORK_PROFILE_PRIVACY_POLICY_INFO_SUMMARY,
- WORK_PROFILE_PRIVACY_POLICY_INFO, CONNECTED_APPS_SEARCH_KEYWORDS,
- WORK_PROFILE_UNIFICATION_SEARCH_KEYWORDS, ACCOUNTS_SEARCH_KEYWORDS,
- CONTROLLED_BY_ADMIN_SUMMARY, WORK_PROFILE_USER_LABEL, WORK_CATEGORY_HEADER,
- PERSONAL_CATEGORY_HEADER,
-
- // PermissionController Strings
- WORK_PROFILE_DEFAULT_APPS_TITLE, HOME_MISSING_WORK_PROFILE_SUPPORT_MESSAGE,
- BACKGROUND_ACCESS_DISABLED_BY_ADMIN_MESSAGE, BACKGROUND_ACCESS_ENABLED_BY_ADMIN_MESSAGE,
- BACKGROUND_ACCESS_ENABLED_BY_ADMIN_MESSAGE, FOREGROUND_ACCESS_ENABLED_BY_ADMIN_MESSAGE,
- LOCATION_AUTO_GRANTED_MESSAGE,
-
- // Dialer Strings
- NOTIFICATION_INCOMING_WORK_CALL_TITLE, NOTIFICATION_ONGOING_WORK_CALL_TITLE,
- NOTIFICATION_MISSED_WORK_CALL_TITLE, NOTIFICATION_WIFI_WORK_CALL_LABEL,
- })
- public @interface UpdatableStringId {
- }
+ public static final String UNDEFINED = "UNDEFINED";
/**
* Class containing the identifiers used to update device management-related system drawable.
+ *
+ * @hide
*/
public static final class Drawables {
@@ -536,11 +49,6 @@
}
/**
- * An ID for any drawable that can't be updated.
- */
- public static final String UNDEFINED = "UNDEFINED";
-
- /**
* Specifically used to badge work profile app icons.
*/
public static final String WORK_PROFILE_ICON_BADGE = "WORK_PROFILE_ICON_BADGE";
@@ -562,20 +70,6 @@
public static final String WORK_PROFILE_USER_ICON = "WORK_PROFILE_USER_ICON";
/**
- * @hide
- */
- public static final Set<String> UPDATABLE_DRAWABLE_IDS = buildDrawablesSet();
-
- private static Set<String> buildDrawablesSet() {
- Set<String> drawables = new HashSet<>();
- drawables.add(WORK_PROFILE_ICON_BADGE);
- drawables.add(WORK_PROFILE_ICON);
- drawables.add(WORK_PROFILE_OFF_ICON);
- drawables.add(WORK_PROFILE_USER_ICON);
- return drawables;
- }
-
- /**
* Class containing the source identifiers used to update device management-related system
* drawable.
*/
@@ -585,12 +79,6 @@
}
/**
- * A source identifier indicating that the updatable resource is used in a generic
- * undefined location.
- */
- public static final String UNDEFINED = "UNDEFINED";
-
- /**
* A source identifier indicating that the updatable drawable is used in notifications.
*/
public static final String NOTIFICATION = "NOTIFICATION";
@@ -622,42 +110,18 @@
* A source identifier indicating that the updatable drawable is used in the status bar.
*/
public static final String STATUS_BAR = "STATUS_BAR";
-
- /**
- * @hide
- */
- public static final Set<String> UPDATABLE_DRAWABLE_SOURCES = buildSourcesSet();
-
- private static Set<String> buildSourcesSet() {
- Set<String> sources = new HashSet<>();
- sources.add(UNDEFINED);
- sources.add(NOTIFICATION);
- sources.add(PROFILE_SWITCH_ANIMATION);
- sources.add(HOME_WIDGET);
- sources.add(LAUNCHER_OFF_BUTTON);
- sources.add(QUICK_SETTINGS);
- sources.add(STATUS_BAR);
- return sources;
- }
}
/**
* Class containing the style identifiers used to update device management-related system
* drawable.
*/
- @SuppressLint("StaticUtils")
public static final class Style {
private Style() {
}
/**
- * A style identifier indicating that the updatable drawable should use the default
- * style.
- */
- public static final String DEFAULT = "DEFAULT";
-
- /**
* A style identifier indicating that the updatable drawable has a solid color fill.
*/
public static final String SOLID_COLORED = "SOLID_COLORED";
@@ -672,20 +136,6 @@
* A style identifier indicating that the updatable drawable is an outline.
*/
public static final String OUTLINE = "OUTLINE";
-
- /**
- * @hide
- */
- public static final Set<String> UPDATABLE_DRAWABLE_STYLES = buildStylesSet();
-
- private static Set<String> buildStylesSet() {
- Set<String> styles = new HashSet<>();
- styles.add(DEFAULT);
- styles.add(SOLID_COLORED);
- styles.add(SOLID_NOT_COLORED);
- styles.add(OUTLINE);
- return styles;
- }
}
}
@@ -701,29 +151,6 @@
}
/**
- * An ID for any string that can't be updated.
- */
- public static final String UNDEFINED = "UNDEFINED";
-
- /**
- * @hide
- */
- public static final Set<String> UPDATABLE_STRING_IDS = buildStringsSet();
-
- private static Set<String> buildStringsSet() {
- Set<String> strings = new HashSet<>();
- strings.addAll(Settings.buildStringsSet());
- strings.addAll(Launcher.buildStringsSet());
- strings.addAll(SystemUi.buildStringsSet());
- strings.addAll(Core.buildStringsSet());
- strings.addAll(DocumentsUi.buildStringsSet());
- strings.addAll(MediaProvider.buildStringsSet());
- strings.addAll(PermissionController.buildStringsSet());
- strings.addAll(Dialer.buildStringsSet());
- return strings;
- }
-
- /**
* Class containing the identifiers used to update device management-related system strings
* in the Settings package
*
@@ -1747,288 +1174,6 @@
* Header for items under the personal user
*/
public static final String PERSONAL_CATEGORY_HEADER = PREFIX + "category_personal";
-
- /**
- * @hide
- */
- static Set<String> buildStringsSet() {
- Set<String> strings = new HashSet<>();
- strings.add(FACE_SETTINGS_FOR_WORK_TITLE);
- strings.add(WORK_PROFILE_FINGERPRINT_LAST_DELETE_MESSAGE);
- strings.add(WORK_PROFILE_IT_ADMIN_CANT_RESET_SCREEN_LOCK);
- strings.add(WORK_PROFILE_SCREEN_LOCK_SETUP_MESSAGE);
- strings.add(WORK_PROFILE_SET_UNLOCK_LAUNCH_PICKER_TITLE);
- strings.add(WORK_PROFILE_LAST_PATTERN_ATTEMPT_BEFORE_WIPE);
- strings.add(WORK_PROFILE_LAST_PIN_ATTEMPT_BEFORE_WIPE);
- strings.add(WORK_PROFILE_LAST_PASSWORD_ATTEMPT_BEFORE_WIPE);
- strings.add(WORK_PROFILE_LOCK_ATTEMPTS_FAILED);
- strings.add(ACCESSIBILITY_CATEGORY_WORK);
- strings.add(ACCESSIBILITY_CATEGORY_PERSONAL);
- strings.add(ACCESSIBILITY_WORK_ACCOUNT_TITLE);
- strings.add(ACCESSIBILITY_PERSONAL_ACCOUNT_TITLE);
- strings.add(WORK_PROFILE_LOCATION_SWITCH_TITLE);
- strings.add(SET_WORK_PROFILE_PASSWORD_HEADER);
- strings.add(SET_WORK_PROFILE_PIN_HEADER);
- strings.add(SET_WORK_PROFILE_PATTERN_HEADER);
- strings.add(CONFIRM_WORK_PROFILE_PASSWORD_HEADER);
- strings.add(CONFIRM_WORK_PROFILE_PIN_HEADER);
- strings.add(CONFIRM_WORK_PROFILE_PATTERN_HEADER);
- strings.add(REENTER_WORK_PROFILE_PASSWORD_HEADER);
- strings.add(REENTER_WORK_PROFILE_PIN_HEADER);
- strings.add(WORK_PROFILE_CONFIRM_PATTERN);
- strings.add(WORK_PROFILE_CONFIRM_PIN);
- strings.add(WORK_PROFILE_PASSWORD_REQUIRED);
- strings.add(WORK_PROFILE_SECURITY_TITLE);
- strings.add(WORK_PROFILE_UNIFY_LOCKS_TITLE);
- strings.add(WORK_PROFILE_UNIFY_LOCKS_SUMMARY);
- strings.add(WORK_PROFILE_UNIFY_LOCKS_DETAIL);
- strings.add(WORK_PROFILE_UNIFY_LOCKS_NONCOMPLIANT);
- strings.add(WORK_PROFILE_KEYBOARDS_AND_TOOLS);
- strings.add(WORK_PROFILE_NOT_AVAILABLE);
- strings.add(WORK_PROFILE_SETTING);
- strings.add(WORK_PROFILE_SETTING_ON_SUMMARY);
- strings.add(WORK_PROFILE_SETTING_OFF_SUMMARY);
- strings.add(REMOVE_WORK_PROFILE);
- strings.add(DEVICE_OWNER_INSTALLED_CERTIFICATE_AUTHORITY_WARNING);
- strings.add(WORK_PROFILE_INSTALLED_CERTIFICATE_AUTHORITY_WARNING);
- strings.add(WORK_PROFILE_CONFIRM_REMOVE_TITLE);
- strings.add(WORK_PROFILE_CONFIRM_REMOVE_MESSAGE);
- strings.add(WORK_APPS_CANNOT_ACCESS_NOTIFICATION_SETTINGS);
- strings.add(WORK_PROFILE_SOUND_SETTINGS_SECTION_HEADER);
- strings.add(WORK_PROFILE_USE_PERSONAL_SOUNDS_TITLE);
- strings.add(WORK_PROFILE_USE_PERSONAL_SOUNDS_SUMMARY);
- strings.add(WORK_PROFILE_RINGTONE_TITLE);
- strings.add(WORK_PROFILE_NOTIFICATION_RINGTONE_TITLE);
- strings.add(WORK_PROFILE_ALARM_RINGTONE_TITLE);
- strings.add(WORK_PROFILE_SYNC_WITH_PERSONAL_SOUNDS_ACTIVE_SUMMARY);
- strings.add(ENABLE_WORK_PROFILE_SYNC_WITH_PERSONAL_SOUNDS_DIALOG_TITLE);
- strings.add(ENABLE_WORK_PROFILE_SYNC_WITH_PERSONAL_SOUNDS_DIALOG_MESSAGE);
- strings.add(WORK_PROFILE_NOTIFICATIONS_SECTION_HEADER);
- strings.add(WORK_PROFILE_LOCKED_NOTIFICATION_TITLE);
- strings.add(WORK_PROFILE_LOCK_SCREEN_REDACT_NOTIFICATION_TITLE);
- strings.add(WORK_PROFILE_LOCK_SCREEN_REDACT_NOTIFICATION_SUMMARY);
- strings.add(WORK_PROFILE_NOTIFICATION_LISTENER_BLOCKED);
- strings.add(CONNECTED_WORK_AND_PERSONAL_APPS_TITLE);
- strings.add(CONNECTED_APPS_SHARE_PERMISSIONS_AND_DATA);
- strings.add(ONLY_CONNECT_TRUSTED_APPS);
- strings.add(HOW_TO_DISCONNECT_APPS);
- strings.add(CONNECT_APPS_DIALOG_TITLE);
- strings.add(CONNECT_APPS_DIALOG_SUMMARY);
- strings.add(APP_CAN_ACCESS_PERSONAL_DATA);
- strings.add(APP_CAN_ACCESS_PERSONAL_PERMISSIONS);
- strings.add(INSTALL_IN_WORK_PROFILE_TO_CONNECT_PROMPT);
- strings.add(INSTALL_IN_PERSONAL_PROFILE_TO_CONNECT_PROMPT);
- strings.add(WORK_PROFILE_MANAGED_BY);
- strings.add(MANAGED_BY);
- strings.add(WORK_PROFILE_DISABLE_USAGE_ACCESS_WARNING);
- strings.add(DISABLED_BY_IT_ADMIN_TITLE);
- strings.add(CONTACT_YOUR_IT_ADMIN);
- strings.add(WORK_PROFILE_ADMIN_POLICIES_WARNING);
- strings.add(USER_ADMIN_POLICIES_WARNING);
- strings.add(DEVICE_ADMIN_POLICIES_WARNING);
- strings.add(WORK_PROFILE_OFF_CONDITION_TITLE);
- strings.add(MANAGED_PROFILE_SETTINGS_TITLE);
- strings.add(WORK_PROFILE_CONTACT_SEARCH_TITLE);
- strings.add(WORK_PROFILE_CONTACT_SEARCH_SUMMARY);
- strings.add(CROSS_PROFILE_CALENDAR_TITLE);
- strings.add(CROSS_PROFILE_CALENDAR_SUMMARY);
- strings.add(ALWAYS_ON_VPN_PERSONAL_PROFILE);
- strings.add(ALWAYS_ON_VPN_DEVICE);
- strings.add(ALWAYS_ON_VPN_WORK_PROFILE);
- strings.add(CA_CERTS_PERSONAL_PROFILE);
- strings.add(CA_CERTS_WORK_PROFILE);
- strings.add(CA_CERTS_DEVICE);
- strings.add(ADMIN_CAN_LOCK_DEVICE);
- strings.add(ADMIN_CAN_WIPE_DEVICE);
- strings.add(ADMIN_CONFIGURED_FAILED_PASSWORD_WIPE_DEVICE);
- strings.add(ADMIN_CONFIGURED_FAILED_PASSWORD_WIPE_WORK_PROFILE);
- strings.add(DEVICE_MANAGED_WITHOUT_NAME);
- strings.add(DEVICE_MANAGED_WITH_NAME);
- strings.add(WORK_PROFILE_APP_SUBTEXT);
- strings.add(PERSONAL_PROFILE_APP_SUBTEXT);
- strings.add(FINGERPRINT_FOR_WORK);
- strings.add(FACE_UNLOCK_DISABLED);
- strings.add(FINGERPRINT_UNLOCK_DISABLED);
- strings.add(FINGERPRINT_UNLOCK_DISABLED_EXPLANATION);
- strings.add(PIN_RECENTLY_USED);
- strings.add(PASSWORD_RECENTLY_USED);
- strings.add(MANAGE_DEVICE_ADMIN_APPS);
- strings.add(NUMBER_OF_DEVICE_ADMINS_NONE);
- strings.add(NUMBER_OF_DEVICE_ADMINS);
- strings.add(FORGOT_PASSWORD_TITLE);
- strings.add(FORGOT_PASSWORD_TEXT);
- strings.add(ERROR_MOVE_DEVICE_ADMIN);
- strings.add(DEVICE_ADMIN_SETTINGS_TITLE);
- strings.add(REMOVE_DEVICE_ADMIN);
- strings.add(UNINSTALL_DEVICE_ADMIN);
- strings.add(REMOVE_AND_UNINSTALL_DEVICE_ADMIN);
- strings.add(SELECT_DEVICE_ADMIN_APPS);
- strings.add(NO_DEVICE_ADMINS);
- strings.add(ACTIVATE_DEVICE_ADMIN_APP);
- strings.add(ACTIVATE_THIS_DEVICE_ADMIN_APP);
- strings.add(ACTIVATE_DEVICE_ADMIN_APP_TITLE);
- strings.add(NEW_DEVICE_ADMIN_WARNING);
- strings.add(NEW_DEVICE_ADMIN_WARNING_SIMPLIFIED);
- strings.add(ACTIVE_DEVICE_ADMIN_WARNING);
- strings.add(SET_PROFILE_OWNER_TITLE);
- strings.add(SET_PROFILE_OWNER_DIALOG_TITLE);
- strings.add(SET_PROFILE_OWNER_POSTSETUP_WARNING);
- strings.add(OTHER_OPTIONS_DISABLED_BY_ADMIN);
- strings.add(REMOVE_ACCOUNT_FAILED_ADMIN_RESTRICTION);
- strings.add(IT_ADMIN_POLICY_DISABLING_INFO_URL);
- strings.add(SHARE_REMOTE_BUGREPORT_DIALOG_TITLE);
- strings.add(SHARE_REMOTE_BUGREPORT_FINISHED_REQUEST_CONSENT);
- strings.add(SHARE_REMOTE_BUGREPORT_NOT_FINISHED_REQUEST_CONSENT);
- strings.add(SHARING_REMOTE_BUGREPORT_MESSAGE);
- strings.add(MANAGED_DEVICE_INFO);
- strings.add(MANAGED_DEVICE_INFO_SUMMARY);
- strings.add(MANAGED_DEVICE_INFO_SUMMARY_WITH_NAME);
- strings.add(ENTERPRISE_PRIVACY_HEADER);
- strings.add(INFORMATION_YOUR_ORGANIZATION_CAN_SEE_TITLE);
- strings.add(CHANGES_MADE_BY_YOUR_ORGANIZATION_ADMIN_TITLE);
- strings.add(YOUR_ACCESS_TO_THIS_DEVICE_TITLE);
- strings.add(ADMIN_CAN_SEE_WORK_DATA_WARNING);
- strings.add(ADMIN_CAN_SEE_APPS_WARNING);
- strings.add(ADMIN_CAN_SEE_USAGE_WARNING);
- strings.add(ADMIN_CAN_SEE_NETWORK_LOGS_WARNING);
- strings.add(ADMIN_CAN_SEE_BUG_REPORT_WARNING);
- strings.add(ADMIN_CAN_SEE_SECURITY_LOGS_WARNING);
- strings.add(ADMIN_ACTION_NONE);
- strings.add(ADMIN_ACTION_APPS_INSTALLED);
- strings.add(ADMIN_ACTION_APPS_COUNT_ESTIMATED);
- strings.add(ADMIN_ACTIONS_APPS_COUNT_MINIMUM);
- strings.add(ADMIN_ACTION_ACCESS_LOCATION);
- strings.add(ADMIN_ACTION_ACCESS_MICROPHONE);
- strings.add(ADMIN_ACTION_ACCESS_CAMERA);
- strings.add(ADMIN_ACTION_SET_DEFAULT_APPS);
- strings.add(ADMIN_ACTIONS_APPS_COUNT);
- strings.add(ADMIN_ACTION_SET_CURRENT_INPUT_METHOD);
- strings.add(ADMIN_ACTION_SET_INPUT_METHOD_NAME);
- strings.add(ADMIN_ACTION_SET_HTTP_PROXY);
- strings.add(WORK_PROFILE_PRIVACY_POLICY_INFO_SUMMARY);
- strings.add(WORK_PROFILE_PRIVACY_POLICY_INFO);
- strings.add(CONNECTED_APPS_SEARCH_KEYWORDS);
- strings.add(WORK_PROFILE_UNIFICATION_SEARCH_KEYWORDS);
- strings.add(ACCOUNTS_SEARCH_KEYWORDS);
- strings.add(CONTROLLED_BY_ADMIN_SUMMARY);
- strings.add(WORK_PROFILE_USER_LABEL);
- strings.add(WORK_CATEGORY_HEADER);
- strings.add(PERSONAL_CATEGORY_HEADER);
- return strings;
- }
- }
-
- /**
- * Class containing the identifiers used to update device management-related system strings
- * in the Launcher package.
- *
- * @hide
- */
- public static final class Launcher {
-
- private Launcher() {
- }
-
- private static final String PREFIX = "Launcher.";
-
- /**
- * User on-boarding title for work profile apps.
- */
- public static final String WORK_PROFILE_EDU = PREFIX + "WORK_PROFILE_EDU";
-
- /**
- * Action label to finish work profile edu.
- */
- public static final String WORK_PROFILE_EDU_ACCEPT = PREFIX + "WORK_PROFILE_EDU_ACCEPT";
-
- /**
- * Title shown when user opens work apps tab while work profile is paused.
- */
- public static final String WORK_PROFILE_PAUSED_TITLE =
- PREFIX + "WORK_PROFILE_PAUSED_TITLE";
-
- /**
- * Description shown when user opens work apps tab while work profile is paused.
- */
- public static final String WORK_PROFILE_PAUSED_DESCRIPTION =
- PREFIX + "WORK_PROFILE_PAUSED_DESCRIPTION";
-
- /**
- * Shown on the button to pause work profile.
- */
- public static final String WORK_PROFILE_PAUSE_BUTTON =
- PREFIX + "WORK_PROFILE_PAUSE_BUTTON";
-
- /**
- * Shown on the button to enable work profile.
- */
- public static final String WORK_PROFILE_ENABLE_BUTTON =
- PREFIX + "WORK_PROFILE_ENABLE_BUTTON";
-
- /**
- * Label on launcher tab to indicate work apps.
- */
- public static final String ALL_APPS_WORK_TAB = PREFIX + "ALL_APPS_WORK_TAB";
-
- /**
- * Label on launcher tab to indicate personal apps.
- */
- public static final String ALL_APPS_PERSONAL_TAB = PREFIX + "ALL_APPS_PERSONAL_TAB";
-
- /**
- * Accessibility description for launcher tab to indicate work apps.
- */
- public static final String ALL_APPS_WORK_TAB_ACCESSIBILITY =
- PREFIX + "ALL_APPS_WORK_TAB_ACCESSIBILITY";
-
- /**
- * Accessibility description for launcher tab to indicate personal apps.
- */
- public static final String ALL_APPS_PERSONAL_TAB_ACCESSIBILITY =
- PREFIX + "ALL_APPS_PERSONAL_TAB_ACCESSIBILITY";
-
- /**
- * Work folder name.
- */
- public static final String WORK_FOLDER_NAME = PREFIX + "WORK_FOLDER_NAME";
-
- /**
- * Label on widget tab to indicate work app widgets.
- */
- public static final String WIDGETS_WORK_TAB = PREFIX + "WIDGETS_WORK_TAB";
-
- /**
- * Label on widget tab to indicate personal app widgets.
- */
- public static final String WIDGETS_PERSONAL_TAB = PREFIX + "WIDGETS_PERSONAL_TAB";
-
- /**
- * Message shown when a feature is disabled by the admin (e.g. changing wallpaper).
- */
- public static final String DISABLED_BY_ADMIN_MESSAGE =
- PREFIX + "DISABLED_BY_ADMIN_MESSAGE";
-
- /**
- * @hide
- */
- static Set<String> buildStringsSet() {
- Set<String> strings = new HashSet<>();
- strings.add(WORK_PROFILE_EDU);
- strings.add(WORK_PROFILE_EDU_ACCEPT);
- strings.add(WORK_PROFILE_PAUSED_TITLE);
- strings.add(WORK_PROFILE_PAUSED_DESCRIPTION);
- strings.add(WORK_PROFILE_PAUSE_BUTTON);
- strings.add(WORK_PROFILE_ENABLE_BUTTON);
- strings.add(ALL_APPS_WORK_TAB);
- strings.add(ALL_APPS_PERSONAL_TAB);
- strings.add(ALL_APPS_PERSONAL_TAB_ACCESSIBILITY);
- strings.add(ALL_APPS_WORK_TAB_ACCESSIBILITY);
- strings.add(WORK_FOLDER_NAME);
- strings.add(WIDGETS_WORK_TAB);
- strings.add(WIDGETS_PERSONAL_TAB);
- strings.add(DISABLED_BY_ADMIN_MESSAGE);
- return strings;
- }
}
/**
@@ -2272,49 +1417,6 @@
* Content description for the work profile lock screen.
*/
public static final String WORK_LOCK_ACCESSIBILITY = PREFIX + "WORK_LOCK_ACCESSIBILITY";
-
- /**
- * @hide
- */
- static Set<String> buildStringsSet() {
- Set<String> strings = new HashSet<>();
- strings.add(QS_WORK_PROFILE_LABEL);
- strings.add(QS_MSG_MANAGEMENT);
- strings.add(QS_MSG_NAMED_MANAGEMENT);
- strings.add(QS_MSG_MANAGEMENT_MONITORING);
- strings.add(QS_MSG_NAMED_MANAGEMENT_MONITORING);
- strings.add(QS_MSG_MANAGEMENT_NAMED_VPN);
- strings.add(QS_MSG_NAMED_MANAGEMENT_NAMED_VPN);
- strings.add(QS_MSG_MANAGEMENT_MULTIPLE_VPNS);
- strings.add(QS_MSG_NAMED_MANAGEMENT_MULTIPLE_VPNS);
- strings.add(QS_MSG_WORK_PROFILE_MONITORING);
- strings.add(QS_MSG_NAMED_WORK_PROFILE_MONITORING);
- strings.add(QS_MSG_WORK_PROFILE_NETWORK);
- strings.add(QS_MSG_WORK_PROFILE_NAMED_VPN);
- strings.add(QS_MSG_PERSONAL_PROFILE_NAMED_VPN);
- strings.add(QS_DIALOG_MANAGEMENT_TITLE);
- strings.add(QS_DIALOG_VIEW_POLICIES);
- strings.add(QS_DIALOG_MANAGEMENT);
- strings.add(QS_DIALOG_NAMED_MANAGEMENT);
- strings.add(QS_DIALOG_MANAGEMENT_CA_CERT);
- strings.add(QS_DIALOG_WORK_PROFILE_CA_CERT);
- strings.add(QS_DIALOG_MANAGEMENT_NETWORK);
- strings.add(QS_DIALOG_WORK_PROFILE_NETWORK);
- strings.add(QS_DIALOG_MANAGEMENT_NAMED_VPN);
- strings.add(QS_DIALOG_MANAGEMENT_TWO_NAMED_VPN);
- strings.add(QS_DIALOG_WORK_PROFILE_NAMED_VPN);
- strings.add(QS_DIALOG_PERSONAL_PROFILE_NAMED_VPN);
- strings.add(BIOMETRIC_DIALOG_WORK_PIN_LAST_ATTEMPT);
- strings.add(BIOMETRIC_DIALOG_WORK_PATTERN_LAST_ATTEMPT);
- strings.add(BIOMETRIC_DIALOG_WORK_PASSWORD_LAST_ATTEMPT);
- strings.add(BIOMETRIC_DIALOG_WORK_LOCK_FAILED_ATTEMPTS);
- strings.add(STATUS_BAR_WORK_ICON_ACCESSIBILITY);
- strings.add(ONGOING_PRIVACY_DIALOG_WORK);
- strings.add(KEYGUARD_MANAGEMENT_DISCLOSURE);
- strings.add(KEYGUARD_NAMED_MANAGEMENT_DISCLOSURE);
- strings.add(WORK_LOCK_ACCESSIBILITY);
- return strings;
- }
}
/**
@@ -2614,278 +1716,35 @@
*/
public static final String WORK_PROFILE_BADGED_LABEL =
PREFIX + "WORK_PROFILE_BADGED_LABEL";
-
- /**
- * @hide
- */
- static Set<String> buildStringsSet() {
- Set<String> strings = new HashSet<>();
- strings.add(WORK_PROFILE_DELETED_TITLE);
- strings.add(WORK_PROFILE_DELETED_FAILED_PASSWORD_ATTEMPTS_MESSAGE);
- strings.add(WORK_PROFILE_DELETED_GENERIC_MESSAGE);
- strings.add(WORK_PROFILE_DELETED_ORG_OWNED_MESSAGE);
- strings.add(PERSONAL_APP_SUSPENSION_TITLE);
- strings.add(PERSONAL_APP_SUSPENSION_MESSAGE);
- strings.add(PERSONAL_APP_SUSPENSION_SOON_MESSAGE);
- strings.add(PERSONAL_APP_SUSPENSION_TURN_ON_PROFILE);
- strings.add(PRINTING_DISABLED_NAMED_ADMIN);
- strings.add(LOCATION_CHANGED_TITLE);
- strings.add(LOCATION_CHANGED_MESSAGE);
- strings.add(NETWORK_LOGGING_TITLE);
- strings.add(NETWORK_LOGGING_MESSAGE);
- strings.add(NOTIFICATION_WORK_PROFILE_CONTENT_DESCRIPTION);
- strings.add(NOTIFICATION_CHANNEL_DEVICE_ADMIN);
- strings.add(SWITCH_TO_WORK_LABEL);
- strings.add(SWITCH_TO_PERSONAL_LABEL);
- strings.add(FORWARD_INTENT_TO_WORK);
- strings.add(FORWARD_INTENT_TO_PERSONAL);
- strings.add(RESOLVER_WORK_PROFILE_NOT_SUPPORTED);
- strings.add(RESOLVER_PERSONAL_TAB);
- strings.add(RESOLVER_WORK_TAB);
- strings.add(RESOLVER_PERSONAL_TAB_ACCESSIBILITY);
- strings.add(RESOLVER_WORK_TAB_ACCESSIBILITY);
- strings.add(RESOLVER_CROSS_PROFILE_BLOCKED_TITLE);
- strings.add(RESOLVER_CANT_SHARE_WITH_PERSONAL);
- strings.add(RESOLVER_CANT_SHARE_WITH_WORK);
- strings.add(RESOLVER_CANT_ACCESS_PERSONAL);
- strings.add(RESOLVER_CANT_ACCESS_WORK);
- strings.add(RESOLVER_WORK_PAUSED_TITLE);
- strings.add(RESOLVER_NO_WORK_APPS);
- strings.add(RESOLVER_NO_PERSONAL_APPS);
- strings.add(CANT_ADD_ACCOUNT_MESSAGE);
- strings.add(PACKAGE_INSTALLED_BY_DO);
- strings.add(PACKAGE_UPDATED_BY_DO);
- strings.add(PACKAGE_DELETED_BY_DO);
- strings.add(UNLAUNCHABLE_APP_WORK_PAUSED_TITLE);
- strings.add(UNLAUNCHABLE_APP_WORK_PAUSED_MESSAGE);
- strings.add(PROFILE_ENCRYPTED_TITLE);
- strings.add(PROFILE_ENCRYPTED_DETAIL);
- strings.add(PROFILE_ENCRYPTED_MESSAGE);
- strings.add(WORK_PROFILE_BADGED_LABEL);
- return strings;
- }
}
/**
* Class containing the identifiers used to update device management-related system strings
- * in the DocumentsUi package.
+ * in the Dialer app.
+ *
+ * @hide
*/
- public static final class DocumentsUi {
+ public static final class Telecomm {
- private DocumentsUi() {
+ private Telecomm() {
}
- private static final String PREFIX = "DocumentsUi.";
+ private static final String PREFIX = "Telecomm.";
/**
- * Title for error message shown when work profile is turned off.
+ * Missed call notification label, used when there's exactly one missed call from work
+ * contact.
*/
- public static final String WORK_PROFILE_OFF_ERROR_TITLE =
- PREFIX + "WORK_PROFILE_OFF_ERROR_TITLE";
-
- /**
- * Button text shown when work profile is turned off.
- */
- public static final String WORK_PROFILE_OFF_ENABLE_BUTTON =
- PREFIX + "WORK_PROFILE_OFF_ENABLE_BUTTON";
-
- /**
- * Title for error message shown when a user's IT admin does not allow the user to
- * select work files from a personal app.
- */
- public static final String CANT_SELECT_WORK_FILES_TITLE =
- PREFIX + "CANT_SELECT_WORK_FILES_TITLE";
-
- /**
- * Message shown when a user's IT admin does not allow the user to select work files
- * from a personal app.
- */
- public static final String CANT_SELECT_WORK_FILES_MESSAGE =
- PREFIX + "CANT_SELECT_WORK_FILES_MESSAGE";
-
- /**
- * Title for error message shown when a user's IT admin does not allow the user to
- * select personal files from a work app.
- */
- public static final String CANT_SELECT_PERSONAL_FILES_TITLE =
- PREFIX + "CANT_SELECT_PERSONAL_FILES_TITLE";
-
- /**
- * Message shown when a user's IT admin does not allow the user to select personal files
- * from a work app.
- */
- public static final String CANT_SELECT_PERSONAL_FILES_MESSAGE =
- PREFIX + "CANT_SELECT_PERSONAL_FILES_MESSAGE";
-
- /**
- * Title for error message shown when a user's IT admin does not allow the user to save
- * files from their personal profile to their work profile.
- */
- public static final String CANT_SAVE_TO_WORK_TITLE =
- PREFIX + "CANT_SAVE_TO_WORK_TITLE";
-
- /**
- * Message shown when a user's IT admin does not allow the user to save files from their
- * personal profile to their work profile.
- */
- public static final String CANT_SAVE_TO_WORK_MESSAGE =
- PREFIX + "CANT_SAVE_TO_WORK_MESSAGE";
-
- /**
- * Title for error message shown when a user's IT admin does not allow the user to save
- * files from their work profile to their personal profile.
- */
- public static final String CANT_SAVE_TO_PERSONAL_TITLE =
- PREFIX + "CANT_SAVE_TO_PERSONAL_TITLE";
-
- /**
- * Message shown when a user's IT admin does not allow the user to save files from their
- * work profile to their personal profile.
- */
- public static final String CANT_SAVE_TO_PERSONAL_MESSAGE =
- PREFIX + "CANT_SAVE_TO_PERSONAL_MESSAGE";
-
- /**
- * Title for error message shown when a user tries to do something on their work
- * device, but that action isn't allowed by their IT admin.
- */
- public static final String CROSS_PROFILE_NOT_ALLOWED_TITLE =
- PREFIX + "CROSS_PROFILE_NOT_ALLOWED_TITLE";
-
- /**
- * Message shown when a user tries to do something on their work device, but that action
- * isn't allowed by their IT admin.
- */
- public static final String CROSS_PROFILE_NOT_ALLOWED_MESSAGE =
- PREFIX + "CROSS_PROFILE_NOT_ALLOWED_MESSAGE";
-
- /**
- * Content description text that's spoken by a screen reader for previewing a work file
- * before opening it. Accepts file name as a param.
- */
- public static final String PREVIEW_WORK_FILE_ACCESSIBILITY =
- PREFIX + "PREVIEW_WORK_FILE_ACCESSIBILITY";
-
- /**
- * Label for tab and sidebar to indicate personal content.
- */
- public static final String PERSONAL_TAB = PREFIX + "PERSONAL_TAB";
-
- /**
- * Label for tab and sidebar tab to indicate work content
- */
- public static final String WORK_TAB = PREFIX + "WORK_TAB";
-
- /**
- * Accessibility label to indicate the subject(e.g. file/folder) is from work profile.
- */
- public static final String WORK_ACCESSIBILITY = PREFIX + "WORK_ACCESSIBILITY";
-
- /**
- * @hide
- */
- static Set<String> buildStringsSet() {
- Set<String> strings = new HashSet<>();
- strings.add(WORK_PROFILE_OFF_ERROR_TITLE);
- strings.add(WORK_PROFILE_OFF_ENABLE_BUTTON);
- strings.add(CANT_SELECT_WORK_FILES_TITLE);
- strings.add(CANT_SELECT_WORK_FILES_MESSAGE);
- strings.add(CANT_SELECT_PERSONAL_FILES_TITLE);
- strings.add(CANT_SELECT_PERSONAL_FILES_MESSAGE);
- strings.add(CANT_SAVE_TO_WORK_TITLE);
- strings.add(CANT_SAVE_TO_WORK_MESSAGE);
- strings.add(CANT_SAVE_TO_PERSONAL_TITLE);
- strings.add(CANT_SAVE_TO_PERSONAL_MESSAGE);
- strings.add(CROSS_PROFILE_NOT_ALLOWED_TITLE);
- strings.add(CROSS_PROFILE_NOT_ALLOWED_MESSAGE);
- strings.add(PREVIEW_WORK_FILE_ACCESSIBILITY);
- strings.add(PERSONAL_TAB);
- strings.add(WORK_TAB);
- strings.add(WORK_ACCESSIBILITY);
- return strings;
- }
+ public static final String NOTIFICATION_MISSED_WORK_CALL_TITLE =
+ PREFIX + "NOTIFICATION_MISSED_WORK_CALL_TITLE";
}
/**
* Class containing the identifiers used to update device management-related system strings
- * in the MediaProvider module.
- */
- public static final class MediaProvider {
-
- private MediaProvider() {
- }
-
- private static final String PREFIX = "MediaProvider.";
-
- /**
- * The text shown to switch to the work profile in PhotoPicker.
- */
- public static final String SWITCH_TO_WORK_MESSAGE =
- PREFIX + "SWITCH_TO_WORK_MESSAGE";
-
- /**
- * The text shown to switch to the personal profile in PhotoPicker.
- */
- public static final String SWITCH_TO_PERSONAL_MESSAGE =
- PREFIX + "SWITCH_TO_PERSONAL_MESSAGE";
-
- /**
- * The title for error dialog in PhotoPicker when the admin blocks cross user
- * interaction for the intent.
- */
- public static final String BLOCKED_BY_ADMIN_TITLE =
- PREFIX + "BLOCKED_BY_ADMIN_TITLE";
-
- /**
- * The message for error dialog in PhotoPicker when the admin blocks cross user
- * interaction from the personal profile.
- */
- public static final String BLOCKED_FROM_PERSONAL_MESSAGE =
- PREFIX + "BLOCKED_FROM_PERSONAL_MESSAGE";
-
- /**
- * The message for error dialog in PhotoPicker when the admin blocks cross user
- * interaction from the work profile.
- */
- public static final String BLOCKED_FROM_WORK_MESSAGE =
- PREFIX + "BLOCKED_FROM_WORK_MESSAGE";
-
- /**
- * The title of the error dialog in PhotoPicker when the user tries to switch to work
- * content, but work profile is off.
- */
- public static final String WORK_PROFILE_PAUSED_TITLE =
- PREFIX + "WORK_PROFILE_PAUSED_TITLE";
-
- /**
- * The message of the error dialog in PhotoPicker when the user tries to switch to work
- * content, but work profile is off.
- */
- public static final String WORK_PROFILE_PAUSED_MESSAGE =
- PREFIX + "WORK_PROFILE_PAUSED_MESSAGE";
-
- /**
- * @hide
- */
- static Set<String> buildStringsSet() {
- Set<String> strings = new HashSet<>();
- strings.add(SWITCH_TO_WORK_MESSAGE);
- strings.add(SWITCH_TO_PERSONAL_MESSAGE);
- strings.add(BLOCKED_BY_ADMIN_TITLE);
- strings.add(BLOCKED_FROM_PERSONAL_MESSAGE);
- strings.add(BLOCKED_FROM_WORK_MESSAGE);
- strings.add(WORK_PROFILE_PAUSED_TITLE);
- strings.add(WORK_PROFILE_PAUSED_MESSAGE);
- return strings;
- }
- }
-
- /**
- * Class containing the identifiers used to update device management-related system strings
- * in the PermissionController module.
+ * in the Permissions module.
*/
public static final class PermissionController {
-
+
private PermissionController() {
}
@@ -2930,69 +1789,6 @@
*/
public static final String LOCATION_AUTO_GRANTED_MESSAGE =
PREFIX + "LOCATION_AUTO_GRANTED_MESSAGE";
-
- /**
- * @hide
- */
- static Set<String> buildStringsSet() {
- Set<String> strings = new HashSet<>();
- strings.add(WORK_PROFILE_DEFAULT_APPS_TITLE);
- strings.add(HOME_MISSING_WORK_PROFILE_SUPPORT_MESSAGE);
- strings.add(BACKGROUND_ACCESS_DISABLED_BY_ADMIN_MESSAGE);
- strings.add(BACKGROUND_ACCESS_ENABLED_BY_ADMIN_MESSAGE);
- strings.add(FOREGROUND_ACCESS_ENABLED_BY_ADMIN_MESSAGE);
- strings.add(LOCATION_AUTO_GRANTED_MESSAGE);
- return strings;
- }
- }
-
- /**
- * Class containing the identifiers used to update device management-related system strings
- * in the Dialer app.
- */
- public static final class Dialer {
-
- private Dialer() {
- }
-
- private static final String PREFIX = "Dialer.";
-
- /**
- * The title of the in-call notification for an incoming work call.
- */
- public static final String NOTIFICATION_INCOMING_WORK_CALL_TITLE =
- PREFIX + "NOTIFICATION_INCOMING_WORK_CALL_TITLE";
-
- /**
- * The title of the in-call notification for an ongoing work call.
- */
- public static final String NOTIFICATION_ONGOING_WORK_CALL_TITLE =
- PREFIX + "NOTIFICATION_ONGOING_WORK_CALL_TITLE";
-
- /**
- * Missed call notification label, used when there's exactly one missed call from work
- * contact.
- */
- public static final String NOTIFICATION_MISSED_WORK_CALL_TITLE =
- PREFIX + "NOTIFICATION_MISSED_WORK_CALL_TITLE";
-
- /**
- * Label for notification indicating that call is being made over wifi.
- */
- public static final String NOTIFICATION_WIFI_WORK_CALL_LABEL =
- PREFIX + "NOTIFICATION_WIFI_WORK_CALL_LABEL";
-
- /**
- * @hide
- */
- static Set<String> buildStringsSet() {
- Set<String> strings = new HashSet<>();
- strings.add(NOTIFICATION_INCOMING_WORK_CALL_TITLE);
- strings.add(NOTIFICATION_ONGOING_WORK_CALL_TITLE);
- strings.add(NOTIFICATION_MISSED_WORK_CALL_TITLE);
- strings.add(NOTIFICATION_WIFI_WORK_CALL_LABEL);
- return strings;
- }
}
}
}
diff --git a/core/java/android/app/admin/DevicePolicyResourcesManager.java b/core/java/android/app/admin/DevicePolicyResourcesManager.java
new file mode 100644
index 0000000..0672922
--- /dev/null
+++ b/core/java/android/app/admin/DevicePolicyResourcesManager.java
@@ -0,0 +1,528 @@
+/*
+ * 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.app.admin;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.annotation.RequiresPermission;
+import android.annotation.SuppressLint;
+import android.annotation.SystemApi;
+import android.content.Context;
+import android.content.res.Resources;
+import android.graphics.drawable.Drawable;
+import android.graphics.drawable.Icon;
+import android.os.RemoteException;
+import android.util.DisplayMetrics;
+import android.util.Log;
+
+import java.util.ArrayList;
+import java.util.Objects;
+import java.util.Set;
+import java.util.function.Supplier;
+
+/**
+ * Class containing required APIs to set, reset, and get device policy related resources.
+ */
+public class DevicePolicyResourcesManager {
+ private static String TAG = "DevicePolicyResourcesManager";
+
+ private final Context mContext;
+ private final IDevicePolicyManager mService;
+
+ /**
+ * @hide
+ */
+ protected DevicePolicyResourcesManager(Context context, IDevicePolicyManager service) {
+ mContext = context;
+ mService = service;
+ }
+
+ /**
+ * For each {@link DevicePolicyDrawableResource} item in {@code drawables}, if
+ * {@link DevicePolicyDrawableResource#getDrawableSource()} is not set, it updates the drawable
+ * resource for the combination of {@link DevicePolicyDrawableResource#getDrawableId()} and
+ * {@link DevicePolicyDrawableResource#getDrawableStyle()} to the drawable with resource ID
+ * {@link DevicePolicyDrawableResource#getResourceIdInCallingPackage()},
+ * meaning any system UI surface calling {@link #getDrawable} with {@code drawableId} and
+ * {@code drawableStyle} will get the new resource after this API is called.
+ *
+ * <p>Otherwise, if {@link DevicePolicyDrawableResource#getDrawableSource()} is set, it
+ * overrides any drawables that was set for the same {@code drawableId} and
+ * {@code drawableStyle} for the provided source.
+ *
+ * <p>Sends a broadcast with action
+ * {@link DevicePolicyManager#ACTION_DEVICE_POLICY_RESOURCE_UPDATED} to registered receivers
+ * when a resource has been updated successfully.
+ *
+ * <p>Important notes to consider when using this API:
+ * <ul>
+ * <li>{@link #getDrawable} references the resource
+ * {@link DevicePolicyDrawableResource#getResourceIdInCallingPackage()} in the
+ * calling package each time it gets called. You have to ensure that the resource is always
+ * available in the calling package as long as it is used as an updated resource.
+ * <li>You still have to re-call {@code setDrawables} even if you only make changes to the
+ * content of the resource with ID
+ * {@link DevicePolicyDrawableResource#getResourceIdInCallingPackage()} as the content might be
+ * cached and would need updating.
+ * </ul>
+ *
+ * @param drawables The list of {@link DevicePolicyDrawableResource} to update.
+ *
+ * @hide
+ */
+ @SystemApi
+ @RequiresPermission(android.Manifest.permission.UPDATE_DEVICE_MANAGEMENT_RESOURCES)
+ public void setDrawables(@NonNull Set<DevicePolicyDrawableResource> drawables) {
+ if (mService != null) {
+ try {
+ mService.setDrawables(new ArrayList<>(drawables));
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+ }
+
+ /**
+ * Removes all updated drawables for the list of {@code drawableIds} that was previously set by
+ * calling {@link #setDrawables}, meaning any subsequent calls to {@link #getDrawable} for the
+ * provided IDs with any {@code drawableStyle} and any {@code drawableSource} will return the
+ * default drawable from {@code defaultDrawableLoader}.
+ *
+ * <p>Sends a broadcast with action
+ * {@link DevicePolicyManager#ACTION_DEVICE_POLICY_RESOURCE_UPDATED} to registered receivers
+ * when a resource has been reset successfully.
+ *
+ * @param drawableIds The list of IDs to remove.
+ *
+ * @hide
+ */
+ @SystemApi
+ @RequiresPermission(android.Manifest.permission.UPDATE_DEVICE_MANAGEMENT_RESOURCES)
+ public void resetDrawables(@NonNull Set<String> drawableIds) {
+ if (mService != null) {
+ try {
+ mService.resetDrawables(new ArrayList<>(drawableIds));
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+ }
+
+ /**
+ * Returns the appropriate updated drawable for the {@code drawableId} with style
+ * {@code drawableStyle} if one was set using {@code setDrawables}, otherwise returns the
+ * drawable from {@code defaultDrawableLoader}.
+ *
+ * <p>Also returns the drawable from {@code defaultDrawableLoader} if {@code drawableId}
+ * is {@link DevicePolicyResources#UNDEFINED}.
+ *
+ * <p>Calls to this API will not return {@code null} unless no updated drawable was found
+ * and the call to {@code defaultDrawableLoader} returned {@code null}.
+ *
+ * <p>This API uses the screen density returned from {@link Resources#getConfiguration()}, to
+ * set a different value use
+ * {@link #getDrawableForDensity(String, String, int, Supplier)}.
+ *
+ * <p>Callers should register for
+ * {@link DevicePolicyManager#ACTION_DEVICE_POLICY_RESOURCE_UPDATED} to get notified when a
+ * resource has been updated.
+ *
+ * <p>Note that each call to this API loads the resource from the package that called
+ * {@code setDrawables} to set the updated resource.
+ *
+ * @param drawableId The drawable ID to get the updated resource for.
+ * @param drawableStyle The drawable style to use.
+ * @param defaultDrawableLoader To get the default drawable if no updated drawable was set for
+ * the provided params.
+ */
+ @Nullable
+ public Drawable getDrawable(
+ @NonNull String drawableId,
+ @NonNull String drawableStyle,
+ @NonNull Supplier<Drawable> defaultDrawableLoader) {
+ return getDrawable(
+ drawableId, drawableStyle, DevicePolicyResources.UNDEFINED, defaultDrawableLoader);
+ }
+
+ /**
+ * Similar to {@link #getDrawable(String, String, Supplier)}, but also accepts
+ * a {@code drawableSource} which could result in returning a different drawable than
+ * {@link #getDrawable(String, String, Supplier)} if an override was set for that specific
+ * source.
+ *
+ * <p> If {@code drawableSource} is {@link DevicePolicyResources#UNDEFINED}, it returns the
+ * appropriate string for {@code drawableId} and {@code drawableStyle} similar to
+ * {@link #getDrawable(String, String, Supplier)}.
+ *
+ * <p>Calls to this API will not return {@code null} unless no updated drawable was found
+ * and the call to {@code defaultDrawableLoader} returned {@code null}.
+ *
+ * <p>Callers should register for
+ * {@link DevicePolicyManager#ACTION_DEVICE_POLICY_RESOURCE_UPDATED} to get notified when a
+ * resource has been updated.
+ *
+ * @param drawableId The drawable ID to get the updated resource for.
+ * @param drawableStyle The drawable style to use.
+ * @param drawableSource The source for the caller.
+ * @param defaultDrawableLoader To get the default drawable if no updated drawable was set for
+ * the provided params.
+ */
+ @Nullable
+ public Drawable getDrawable(
+ @NonNull String drawableId,
+ @NonNull String drawableStyle,
+ @NonNull String drawableSource,
+ @NonNull Supplier<Drawable> defaultDrawableLoader) {
+
+ Objects.requireNonNull(drawableId, "drawableId can't be null");
+ Objects.requireNonNull(drawableStyle, "drawableStyle can't be null");
+ Objects.requireNonNull(drawableSource, "drawableSource can't be null");
+ Objects.requireNonNull(defaultDrawableLoader, "defaultDrawableLoader can't be null");
+
+ if (drawableId.equals(DevicePolicyResources.UNDEFINED)) {
+ return ParcelableResource.loadDefaultDrawable(defaultDrawableLoader);
+ }
+ if (mService != null) {
+ try {
+ ParcelableResource resource = mService.getDrawable(
+ drawableId, drawableStyle, drawableSource);
+ if (resource == null) {
+ return ParcelableResource.loadDefaultDrawable(
+ defaultDrawableLoader);
+ }
+ return resource.getDrawable(
+ mContext,
+ /* density= */ 0,
+ defaultDrawableLoader);
+
+ } catch (RemoteException e) {
+ Log.e(
+ TAG,
+ "Error getting the updated drawable from DevicePolicyManagerService.",
+ e);
+ return ParcelableResource.loadDefaultDrawable(defaultDrawableLoader);
+ }
+ }
+ return ParcelableResource.loadDefaultDrawable(defaultDrawableLoader);
+ }
+
+ /**
+ * Similar to {@link #getDrawable(String, String, Supplier)}, but also accepts
+ * {@code density}. See {@link Resources#getDrawableForDensity(int, int, Resources.Theme)}.
+ *
+ * <p>Calls to this API will not return {@code null} unless no updated drawable was found
+ * and the call to {@code defaultDrawableLoader} returned {@code null}.
+ *
+ * <p>Callers should register for
+ * {@link DevicePolicyManager#ACTION_DEVICE_POLICY_RESOURCE_UPDATED} to get notified when a
+ * resource has been updated.
+ *
+ * @param drawableId The drawable ID to get the updated resource for.
+ * @param drawableStyle The drawable style to use.
+ * @param density The desired screen density indicated by the resource as
+ * found in {@link DisplayMetrics}. A value of 0 means to use the
+ * density returned from {@link Resources#getConfiguration()}.
+ * @param defaultDrawableLoader To get the default drawable if no updated drawable was set for
+ * the provided params.
+ */
+ @Nullable
+ public Drawable getDrawableForDensity(
+ @NonNull String drawableId,
+ @NonNull String drawableStyle,
+ int density,
+ @NonNull Supplier<Drawable> defaultDrawableLoader) {
+ return getDrawableForDensity(
+ drawableId,
+ drawableStyle,
+ DevicePolicyResources.UNDEFINED,
+ density,
+ defaultDrawableLoader);
+ }
+
+ /**
+ * Similar to {@link #getDrawable(String, String, String, Supplier)}, but also accepts
+ * {@code density}. See {@link Resources#getDrawableForDensity(int, int, Resources.Theme)}.
+ *
+ * <p>Calls to this API will not return {@code null} unless no updated drawable was found
+ * and the call to {@code defaultDrawableLoader} returned {@code null}.
+ *
+ * <p>Callers should register for
+ * {@link DevicePolicyManager#ACTION_DEVICE_POLICY_RESOURCE_UPDATED} to get notified when a
+ * resource has been updated.
+ *
+ * @param drawableId The drawable ID to get the updated resource for.
+ * @param drawableStyle The drawable style to use.
+ * @param drawableSource The source for the caller.
+ * @param density The desired screen density indicated by the resource as
+ * found in {@link DisplayMetrics}. A value of 0 means to use the
+ * density returned from {@link Resources#getConfiguration()}.
+ * @param defaultDrawableLoader To get the default drawable if no updated drawable was set for
+ * the provided params.
+ */
+ @Nullable
+ public Drawable getDrawableForDensity(
+ @NonNull String drawableId,
+ @NonNull String drawableStyle,
+ @NonNull String drawableSource,
+ int density,
+ @NonNull Supplier<Drawable> defaultDrawableLoader) {
+
+ Objects.requireNonNull(drawableId, "drawableId can't be null");
+ Objects.requireNonNull(drawableStyle, "drawableStyle can't be null");
+ Objects.requireNonNull(drawableSource, "drawableSource can't be null");
+ Objects.requireNonNull(defaultDrawableLoader, "defaultDrawableLoader can't be null");
+
+ if (drawableId.equals(DevicePolicyResources.UNDEFINED)) {
+ return ParcelableResource.loadDefaultDrawable(defaultDrawableLoader);
+ }
+ if (mService != null) {
+ try {
+ ParcelableResource resource = mService.getDrawable(
+ drawableId, drawableStyle, drawableSource);
+ if (resource == null) {
+ return ParcelableResource.loadDefaultDrawable(
+ defaultDrawableLoader);
+ }
+ return resource.getDrawable(mContext, density, defaultDrawableLoader);
+ } catch (RemoteException e) {
+ Log.e(
+ TAG,
+ "Error getting the updated drawable from DevicePolicyManagerService.",
+ e);
+ return ParcelableResource.loadDefaultDrawable(defaultDrawableLoader);
+ }
+ }
+ return ParcelableResource.loadDefaultDrawable(defaultDrawableLoader);
+ }
+
+ /**
+ * Similar to {@link #getDrawable(String, String, String, Supplier)} but returns an
+ * {@link Icon} instead of a {@link Drawable}.
+ *
+ * @param drawableId The drawable ID to get the updated resource for.
+ * @param drawableStyle The drawable style to use.
+ * @param drawableSource The source for the caller.
+ * @param defaultIcon Returned if no updated drawable was set for the provided params.
+ */
+ @Nullable
+ public Icon getDrawableAsIcon(
+ @NonNull String drawableId,
+ @NonNull String drawableStyle,
+ @NonNull String drawableSource,
+ @Nullable Icon defaultIcon) {
+ Objects.requireNonNull(drawableId, "drawableId can't be null");
+ Objects.requireNonNull(drawableStyle, "drawableStyle can't be null");
+ Objects.requireNonNull(drawableSource, "drawableSource can't be null");
+ Objects.requireNonNull(defaultIcon, "defaultIcon can't be null");
+
+ if (drawableId.equals(DevicePolicyResources.UNDEFINED)) {
+ return defaultIcon;
+ }
+ if (mService != null) {
+ try {
+ ParcelableResource resource = mService.getDrawable(
+ drawableId, drawableStyle, drawableSource);
+ if (resource == null) {
+ return defaultIcon;
+ }
+ return Icon.createWithResource(resource.getPackageName(), resource.getResourceId());
+ } catch (RemoteException e) {
+ Log.e(
+ TAG,
+ "Error getting the updated drawable from DevicePolicyManagerService.",
+ e);
+ return defaultIcon;
+ }
+ }
+ return defaultIcon;
+ }
+
+ /**
+ * Similar to {@link #getDrawable(String, String, Supplier)} but returns an {@link Icon}
+ * instead of a {@link Drawable}.
+ *
+ * @param drawableId The drawable ID to get the updated resource for.
+ * @param drawableStyle The drawable style to use.
+ * @param defaultIcon Returned if no updated drawable was set for the provided params.
+ */
+ @Nullable
+ public Icon getDrawableAsIcon(
+ @NonNull String drawableId,
+ @NonNull String drawableStyle,
+ @Nullable Icon defaultIcon) {
+ return getDrawableAsIcon(
+ drawableId, drawableStyle, DevicePolicyResources.UNDEFINED, defaultIcon);
+ }
+
+
+ /**
+ * For each {@link DevicePolicyStringResource} item in {@code strings}, it updates the string
+ * resource for {@link DevicePolicyStringResource#getStringId()} to the string with ID
+ * {@code callingPackageResourceId}, meaning any system UI surface calling {@link #getString}
+ * with {@code stringId} will get the new resource after this API is called.
+ *
+ * <p>Sends a broadcast with action
+ * {@link DevicePolicyManager#ACTION_DEVICE_POLICY_RESOURCE_UPDATED} to registered receivers
+ * when a resource has been updated successfully.
+ *
+ * <p>Important notes to consider when using this API:
+ * <ul>
+ * <li> {@link #getString} references the resource {@code callingPackageResourceId} in the
+ * calling package each time it gets called. You have to ensure that the resource is always
+ * available in the calling package as long as it is used as an updated resource.
+ * <li> You still have to re-call {@code setStrings} even if you only make changes to the
+ * content of the resource with ID {@code callingPackageResourceId} as the content might be
+ * cached and would need updating.
+ * </ul>
+ *
+ * @param strings The list of {@link DevicePolicyStringResource} to update.
+ *
+ * @hide
+ */
+ @SystemApi
+ @RequiresPermission(android.Manifest.permission.UPDATE_DEVICE_MANAGEMENT_RESOURCES)
+ public void setStrings(@NonNull Set<DevicePolicyStringResource> strings) {
+ if (mService != null) {
+ try {
+ mService.setStrings(new ArrayList<>(strings));
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+ }
+
+ /**
+ * Removes the updated strings for the list of {@code stringIds} that was previously set by
+ * calling {@link #setStrings}, meaning any subsequent calls to {@link #getString} for the
+ * provided IDs will return the default string from {@code defaultStringLoader}.
+ *
+ * <p>Sends a broadcast with action
+ * {@link DevicePolicyManager#ACTION_DEVICE_POLICY_RESOURCE_UPDATED} to registered receivers
+ * when a resource has been reset successfully.
+ *
+ * @param stringIds The list of IDs to remove the updated resources for.
+ *
+ * @hide
+ */
+ @SystemApi
+ @RequiresPermission(android.Manifest.permission.UPDATE_DEVICE_MANAGEMENT_RESOURCES)
+ public void resetStrings(@NonNull Set<String> stringIds) {
+ if (mService != null) {
+ try {
+ mService.resetStrings(new ArrayList<>(stringIds));
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+ }
+
+ /**
+ * Returns the appropriate updated string for the {@code stringId} (see
+ * {@link DevicePolicyResources.Strings}) if one was set using
+ * {@code setStrings}, otherwise returns the string from {@code defaultStringLoader}.
+ *
+ * <p>Also returns the string from {@code defaultStringLoader} if {@code stringId} is
+ * {@link DevicePolicyResources#UNDEFINED}.
+ *
+ * <p>Calls to this API will not return {@code null} unless no updated drawable was found
+ * and the call to {@code defaultStringLoader} returned {@code null}.
+ *
+ * <p>Callers should register for
+ * {@link DevicePolicyManager#ACTION_DEVICE_POLICY_RESOURCE_UPDATED} to get notified when a
+ * resource has been updated.
+ *
+ * <p>Note that each call to this API loads the resource from the package that called
+ * {@code setStrings} to set the updated resource.
+ *
+ * @param stringId The IDs to get the updated resource for.
+ * @param defaultStringLoader To get the default string if no updated string was set for
+ * {@code stringId}.
+ */
+ @Nullable
+ public String getString(
+ @NonNull String stringId,
+ @NonNull Supplier<String> defaultStringLoader) {
+
+ Objects.requireNonNull(stringId, "stringId can't be null");
+ Objects.requireNonNull(defaultStringLoader, "defaultStringLoader can't be null");
+
+ if (stringId.equals(DevicePolicyResources.UNDEFINED)) {
+ return ParcelableResource.loadDefaultString(defaultStringLoader);
+ }
+ if (mService != null) {
+ try {
+ ParcelableResource resource = mService.getString(stringId);
+ if (resource == null) {
+ return ParcelableResource.loadDefaultString(defaultStringLoader);
+ }
+ return resource.getString(mContext, defaultStringLoader);
+ } catch (RemoteException e) {
+ Log.e(
+ TAG,
+ "Error getting the updated string from DevicePolicyManagerService.",
+ e);
+ return ParcelableResource.loadDefaultString(defaultStringLoader);
+ }
+ }
+ return ParcelableResource.loadDefaultString(defaultStringLoader);
+ }
+
+ /**
+ * Similar to {@link #getString(String, Supplier)} but accepts {@code formatArgs} and returns a
+ * localized formatted string, substituting the format arguments as defined in
+ * {@link java.util.Formatter} and {@link java.lang.String#format}, (see
+ * {@link Resources#getString(int, Object...)}).
+ *
+ * <p>Calls to this API will not return {@code null} unless no updated drawable was found
+ * and the call to {@code defaultStringLoader} returned {@code null}.
+ *
+ * @param stringId The IDs to get the updated resource for.
+ * @param defaultStringLoader To get the default string if no updated string was set for
+ * {@code stringId}.
+ * @param formatArgs The format arguments that will be used for substitution.
+ */
+ @Nullable
+ @SuppressLint("SamShouldBeLast")
+ public String getString(
+ @NonNull String stringId,
+ @NonNull Supplier<String> defaultStringLoader,
+ @NonNull Object... formatArgs) {
+
+ Objects.requireNonNull(stringId, "stringId can't be null");
+ Objects.requireNonNull(defaultStringLoader, "defaultStringLoader can't be null");
+
+ if (stringId.equals(DevicePolicyResources.UNDEFINED)) {
+ return ParcelableResource.loadDefaultString(defaultStringLoader);
+ }
+ if (mService != null) {
+ try {
+ ParcelableResource resource = mService.getString(stringId);
+ if (resource == null) {
+ return ParcelableResource.loadDefaultString(defaultStringLoader);
+ }
+ return resource.getString(mContext, defaultStringLoader, formatArgs);
+ } catch (RemoteException e) {
+ Log.e(
+ TAG,
+ "Error getting the updated string from DevicePolicyManagerService.",
+ e);
+ return ParcelableResource.loadDefaultString(defaultStringLoader);
+ }
+ }
+ return ParcelableResource.loadDefaultString(defaultStringLoader);
+ }
+}
diff --git a/core/java/android/app/admin/DevicePolicyStringResource.java b/core/java/android/app/admin/DevicePolicyStringResource.java
index b36f1408..7e59340 100644
--- a/core/java/android/app/admin/DevicePolicyStringResource.java
+++ b/core/java/android/app/admin/DevicePolicyStringResource.java
@@ -28,19 +28,19 @@
/**
* Used to pass in the required information for updating an enterprise string resource using
- * {@link DevicePolicyManager#setStrings}.
+ * {@link DevicePolicyResourcesManager#setStrings}.
*
* @hide
*/
@SystemApi
public final class DevicePolicyStringResource implements Parcelable {
- @NonNull private final @DevicePolicyResources.UpdatableStringId String mStringId;
+ @NonNull private final String mStringId;
private final @StringRes int mResourceIdInCallingPackage;
@NonNull private ParcelableResource mResource;
/**
* Creates an object containing the required information for updating an enterprise string
- * resource using {@link DevicePolicyManager#setStrings}.
+ * resource using {@link DevicePolicyResourcesManager#setStrings}.
*
* <p>It will be used to update the string defined by {@code stringId} to the string with ID
* {@code resourceIdInCallingPackage} in the calling package</p>
@@ -54,14 +54,14 @@
*/
public DevicePolicyStringResource(
@NonNull Context context,
- @NonNull @DevicePolicyResources.UpdatableStringId String stringId,
+ @NonNull String stringId,
@StringRes int resourceIdInCallingPackage) {
this(stringId, resourceIdInCallingPackage, new ParcelableResource(
context, resourceIdInCallingPackage, ParcelableResource.RESOURCE_TYPE_STRING));
}
private DevicePolicyStringResource(
- @NonNull @DevicePolicyResources.UpdatableStringId String stringId,
+ @NonNull String stringId,
@StringRes int resourceIdInCallingPackage,
@NonNull ParcelableResource resource) {
Objects.requireNonNull(stringId, "stringId must be provided.");
@@ -75,7 +75,6 @@
/**
* Returns the ID of the string to update.
*/
- @DevicePolicyResources.UpdatableStringId
@NonNull
public String getStringId() {
return mStringId;
diff --git a/core/java/android/app/admin/FactoryResetProtectionPolicy.java b/core/java/android/app/admin/FactoryResetProtectionPolicy.java
index 40ae1f0..7e95177 100644
--- a/core/java/android/app/admin/FactoryResetProtectionPolicy.java
+++ b/core/java/android/app/admin/FactoryResetProtectionPolicy.java
@@ -25,6 +25,7 @@
import android.content.ComponentName;
import android.os.Parcel;
import android.os.Parcelable;
+import android.util.IndentingPrintWriter;
import android.util.Log;
import android.util.TypedXmlPullParser;
import android.util.TypedXmlSerializer;
@@ -254,4 +255,18 @@
return !mFactoryResetProtectionAccounts.isEmpty() && mFactoryResetProtectionEnabled;
}
+ /**
+ * @hide
+ */
+ public void dump(IndentingPrintWriter pw) {
+ pw.print("factoryResetProtectionEnabled=");
+ pw.println(mFactoryResetProtectionEnabled);
+
+ pw.print("factoryResetProtectionAccounts=");
+ pw.increaseIndent();
+ for (int i = 0; i < mFactoryResetProtectionAccounts.size(); i++) {
+ pw.println(mFactoryResetProtectionAccounts.get(i));
+ }
+ pw.decreaseIndent();
+ }
}
diff --git a/core/java/android/app/admin/IDevicePolicyManager.aidl b/core/java/android/app/admin/IDevicePolicyManager.aidl
index 77db146..64241aa 100644
--- a/core/java/android/app/admin/IDevicePolicyManager.aidl
+++ b/core/java/android/app/admin/IDevicePolicyManager.aidl
@@ -17,6 +17,7 @@
package android.app.admin;
+import android.accounts.Account;
import android.app.admin.DevicePolicyDrawableResource;
import android.app.admin.DevicePolicyStringResource;
import android.app.admin.ParcelableResource;
@@ -476,7 +477,7 @@
int getGlobalPrivateDnsMode(in ComponentName admin);
String getGlobalPrivateDnsHost(in ComponentName admin);
- void markProfileOwnerOnOrganizationOwnedDevice(in ComponentName who, int userId);
+ void setProfileOwnerOnOrganizationOwnedDevice(in ComponentName who, int userId, boolean isProfileOwnerOnOrganizationOwnedDevice);
void installUpdateFromFile(in ComponentName admin, in ParcelFileDescriptor updateFileDescriptor, in StartInstallingUpdateCallback listener);
@@ -528,6 +529,8 @@
UserHandle createAndProvisionManagedProfile(in ManagedProfileProvisioningParams provisioningParams, in String callerPackage);
void provisionFullyManagedDevice(in FullyManagedDeviceProvisioningParams provisioningParams, in String callerPackage);
+ void finalizeWorkProfileProvisioning(in UserHandle managedProfileUser, in Account migratedAccount);
+
void setDeviceOwnerType(in ComponentName admin, in int deviceOwnerType);
int getDeviceOwnerType(in ComponentName admin);
@@ -549,13 +552,15 @@
List<UserHandle> listForegroundAffiliatedUsers();
void setDrawables(in List<DevicePolicyDrawableResource> drawables);
- void resetDrawables(in String[] drawableIds);
+ void resetDrawables(in List<String> drawableIds);
ParcelableResource getDrawable(String drawableId, String drawableStyle, String drawableSource);
boolean isDpcDownloaded();
void setDpcDownloaded(boolean downloaded);
void setStrings(in List<DevicePolicyStringResource> strings);
- void resetStrings(in String[] stringIds);
+ void resetStrings(in List<String> stringIds);
ParcelableResource getString(String stringId);
+
+ boolean shouldAllowBypassingDevicePolicyManagementRoleQualification();
}
diff --git a/core/java/android/app/admin/ParcelableResource.java b/core/java/android/app/admin/ParcelableResource.java
index bcae284..a297665 100644
--- a/core/java/android/app/admin/ParcelableResource.java
+++ b/core/java/android/app/admin/ParcelableResource.java
@@ -43,7 +43,8 @@
/**
* Used to store the required information to load a resource that was updated using
- * {@link DevicePolicyManager#setDrawables} and {@link DevicePolicyManager#setStrings}.
+ * {@link DevicePolicyResourcesManager#setDrawables} and
+ * {@link DevicePolicyResourcesManager#setStrings}.
*
* @hide
*/
diff --git a/core/java/android/app/prediction/AppTargetEvent.java b/core/java/android/app/prediction/AppTargetEvent.java
index 51e3953..91da8ec 100644
--- a/core/java/android/app/prediction/AppTargetEvent.java
+++ b/core/java/android/app/prediction/AppTargetEvent.java
@@ -60,6 +60,11 @@
*/
public static final int ACTION_UNPIN = 4;
+ /**
+ * Event type constant indicating an app target has been un-dismissed.
+ */
+ public static final int ACTION_UNDISMISS = 5;
+
private final AppTarget mTarget;
private final String mLocation;
private final int mAction;
diff --git a/core/java/android/app/usage/BroadcastResponseStats.java b/core/java/android/app/usage/BroadcastResponseStats.java
index e1d37e1..572c453 100644
--- a/core/java/android/app/usage/BroadcastResponseStats.java
+++ b/core/java/android/app/usage/BroadcastResponseStats.java
@@ -29,6 +29,8 @@
* Class containing a collection of stats related to response events started from an app
* after receiving a broadcast.
*
+ * @see UsageStatsManager#queryBroadcastResponseStats(String, long)
+ * @see UsageStatsManager#clearBroadcastResponseStats(String, long)
* @hide
*/
@SystemApi
diff --git a/core/java/android/app/usage/IUsageStatsManager.aidl b/core/java/android/app/usage/IUsageStatsManager.aidl
index 2a2a9c6..d4fbdc6 100644
--- a/core/java/android/app/usage/IUsageStatsManager.aidl
+++ b/core/java/android/app/usage/IUsageStatsManager.aidl
@@ -74,12 +74,14 @@
int getUsageSource();
void forceUsageSourceSettingRead();
long getLastTimeAnyComponentUsed(String packageName, String callingPackage);
- @JavaPassthrough(annotation="@android.annotation.RequiresPermission(android.Manifest.permission.PACKAGE_USAGE_STATS)")
+ @JavaPassthrough(annotation="@android.annotation.RequiresPermission(android.Manifest.permission.ACCESS_BROADCAST_RESPONSE_STATS)")
BroadcastResponseStatsList queryBroadcastResponseStats(
String packageName, long id, String callingPackage, int userId);
- @JavaPassthrough(annotation="@android.annotation.RequiresPermission(android.Manifest.permission.PACKAGE_USAGE_STATS)")
+ @JavaPassthrough(annotation="@android.annotation.RequiresPermission(android.Manifest.permission.ACCESS_BROADCAST_RESPONSE_STATS)")
void clearBroadcastResponseStats(String packageName, long id, String callingPackage,
int userId);
- @JavaPassthrough(annotation="@android.annotation.RequiresPermission(android.Manifest.permission.PACKAGE_USAGE_STATS)")
+ @JavaPassthrough(annotation="@android.annotation.RequiresPermission(android.Manifest.permission.ACCESS_BROADCAST_RESPONSE_STATS)")
void clearBroadcastEvents(String callingPackage, int userId);
+ @JavaPassthrough(annotation="@android.annotation.RequiresPermission(android.Manifest.permission.READ_DEVICE_CONFIG)")
+ String getAppStandbyConstant(String key);
}
diff --git a/core/java/android/app/usage/UsageStatsManager.java b/core/java/android/app/usage/UsageStatsManager.java
index 3a335f9..c013fcd 100644
--- a/core/java/android/app/usage/UsageStatsManager.java
+++ b/core/java/android/app/usage/UsageStatsManager.java
@@ -16,6 +16,7 @@
package android.app.usage;
+import android.Manifest;
import android.annotation.CurrentTimeMillisLong;
import android.annotation.IntDef;
import android.annotation.IntRange;
@@ -1446,7 +1447,7 @@
* @hide
*/
@SystemApi
- @RequiresPermission(android.Manifest.permission.PACKAGE_USAGE_STATS)
+ @RequiresPermission(android.Manifest.permission.ACCESS_BROADCAST_RESPONSE_STATS)
@UserHandleAware
@NonNull
public List<BroadcastResponseStats> queryBroadcastResponseStats(
@@ -1479,7 +1480,7 @@
* @hide
*/
@SystemApi
- @RequiresPermission(android.Manifest.permission.PACKAGE_USAGE_STATS)
+ @RequiresPermission(android.Manifest.permission.ACCESS_BROADCAST_RESPONSE_STATS)
@UserHandleAware
public void clearBroadcastResponseStats(@Nullable String packageName,
@IntRange(from = 0) long id) {
@@ -1496,7 +1497,7 @@
*
* @hide
*/
- @RequiresPermission(android.Manifest.permission.PACKAGE_USAGE_STATS)
+ @RequiresPermission(android.Manifest.permission.ACCESS_BROADCAST_RESPONSE_STATS)
@UserHandleAware
public void clearBroadcastEvents() {
try {
@@ -1505,4 +1506,15 @@
throw re.rethrowFromSystemServer();
}
}
+
+ /** @hide */
+ @RequiresPermission(Manifest.permission.READ_DEVICE_CONFIG)
+ @Nullable
+ public String getAppStandbyConstant(@NonNull String key) {
+ try {
+ return mService.getAppStandbyConstant(key);
+ } catch (RemoteException re) {
+ throw re.rethrowFromSystemServer();
+ }
+ }
}
diff --git a/core/java/android/content/Context.java b/core/java/android/content/Context.java
index 60efb4d..24b1b6a 100644
--- a/core/java/android/content/Context.java
+++ b/core/java/android/content/Context.java
@@ -6508,22 +6508,22 @@
/**
- * Triggers the asynchronous revocation of a permission.
+ * Triggers the asynchronous revocation of a runtime permission. If the permission is not
+ * currently granted, nothing happens (even if later granted by the user).
*
* @param permName The name of the permission to be revoked.
- * @see #revokeOwnPermissionsOnKill(Collection)
+ * @see #revokeSelfPermissionsOnKill(Collection)
+ * @throws IllegalArgumentException if the permission is not a runtime permission
*/
- public void revokeOwnPermissionOnKill(@NonNull String permName) {
- revokeOwnPermissionsOnKill(Collections.singletonList(permName));
+ public void revokeSelfPermissionOnKill(@NonNull String permName) {
+ revokeSelfPermissionsOnKill(Collections.singletonList(permName));
}
/**
* Triggers the revocation of one or more permissions for the calling package. A package is only
- * able to revoke a permission under the following conditions:
- * <ul>
- * <li>Each permission in {@code permissions} must be granted to the calling package.
- * <li>Each permission in {@code permissions} must be a runtime permission.
- * </ul>
+ * able to revoke runtime permissions. If a permission is not currently granted, it is ignored
+ * and will not get revoked (even if later granted by the user). Ultimately, you should never
+ * make assumptions about a permission status as users may grant or revoke them at any time.
* <p>
* Background permissions which have no corresponding foreground permission still granted once
* the revocation is effective will also be revoked.
@@ -6549,8 +6549,9 @@
* @param permissions Collection of permissions to be revoked.
* @see PackageManager#getGroupOfPlatformPermission(String, Executor, Consumer)
* @see PackageManager#getPlatformPermissionsForGroup(String, Executor, Consumer)
+ * @throws IllegalArgumentException if any of the permissions is not a runtime permission
*/
- public void revokeOwnPermissionsOnKill(@NonNull Collection<String> permissions) {
+ public void revokeSelfPermissionsOnKill(@NonNull Collection<String> permissions) {
throw new AbstractMethodError("Must be overridden in implementing class");
}
@@ -7145,8 +7146,9 @@
}
/**
- * Returns token if the {@link Context} is a {@link android.app.WindowContext}. Returns
- * {@code null} otherwise.
+ * Returns the {@link IBinder} representing the associated
+ * {@link com.android.server.wm.WindowToken} if the {@link Context} is a
+ * {@link android.app.WindowContext}. Returns {@code null} otherwise.
*
* @hide
*/
diff --git a/core/java/android/content/ContextWrapper.java b/core/java/android/content/ContextWrapper.java
index 9adf173..4ecd776 100644
--- a/core/java/android/content/ContextWrapper.java
+++ b/core/java/android/content/ContextWrapper.java
@@ -1036,8 +1036,8 @@
}
@Override
- public void revokeOwnPermissionsOnKill(@NonNull Collection<String> permissions) {
- mBase.revokeOwnPermissionsOnKill(permissions);
+ public void revokeSelfPermissionsOnKill(@NonNull Collection<String> permissions) {
+ mBase.revokeSelfPermissionsOnKill(permissions);
}
@Override
diff --git a/core/java/android/content/Intent.java b/core/java/android/content/Intent.java
index 478befd..a50ff3841 100644
--- a/core/java/android/content/Intent.java
+++ b/core/java/android/content/Intent.java
@@ -5987,22 +5987,6 @@
public static final String EXTRA_UID = "android.intent.extra.UID";
/**
- * Used as an optional int extra field in {@link android.content.Intent#ACTION_PACKAGE_ADDED}
- * intents to supply the previous uid the package had been assigned.
- * This would only be set when a package is leaving sharedUserId in an upgrade, or when a
- * system app upgrade that had left sharedUserId is getting uninstalled.
- */
- public static final String EXTRA_PREVIOUS_UID = "android.intent.extra.PREVIOUS_UID";
-
- /**
- * Used as an optional int extra field in {@link android.content.Intent#ACTION_PACKAGE_REMOVED}
- * intents to supply the new uid the package will be assigned.
- * This would only be set when a package is leaving sharedUserId in an upgrade, or when a
- * system app upgrade that had left sharedUserId is getting uninstalled.
- */
- public static final String EXTRA_NEW_UID = "android.intent.extra.NEW_UID";
-
- /**
* @hide String array of package names.
*/
@SystemApi
@@ -6034,16 +6018,6 @@
public static final String EXTRA_REPLACING = "android.intent.extra.REPLACING";
/**
- * Used as a boolean extra field in {@link android.content.Intent#ACTION_PACKAGE_REMOVED},
- * {@link android.content.Intent#ACTION_UID_REMOVED}, and
- * {@link android.content.Intent#ACTION_PACKAGE_ADDED}
- * intents to indicate that this package is changing its UID.
- * This would only be set when a package is leaving sharedUserId in an upgrade, or when a
- * system app upgrade that had left sharedUserId is getting uninstalled.
- */
- public static final String EXTRA_UID_CHANGING = "android.intent.extra.UID_CHANGING";
-
- /**
* Used as an int extra field in {@link android.app.AlarmManager} pending intents
* to tell the application being invoked how many pending alarms are being
* delivered with the intent. For one-shot alarms this will always be 1.
@@ -8903,8 +8877,12 @@
* @return the value of an item previously added with putExtra(),
* or null if no Parcelable value was found.
*
+ * @deprecated Use the type-safer {@link #getParcelableExtra(String, Class)} starting from
+ * Android {@link Build.VERSION_CODES#TIRAMISU}.
+ *
* @see #putExtra(String, Parcelable)
*/
+ @Deprecated
public @Nullable <T extends Parcelable> T getParcelableExtra(String name) {
return mExtras == null ? null : mExtras.<T>getParcelable(name);
}
@@ -8913,12 +8891,31 @@
* Retrieve extended data from the intent.
*
* @param name The name of the desired item.
+ * @param clazz The type of the object expected.
+ *
+ * @return the value of an item previously added with putExtra(),
+ * or null if no Parcelable value was found.
+ *
+ * @see #putExtra(String, Parcelable)
+ */
+ public @Nullable <T> T getParcelableExtra(@Nullable String name, @NonNull Class<T> clazz) {
+ return mExtras == null ? null : mExtras.getParcelable(name, clazz);
+ }
+
+ /**
+ * Retrieve extended data from the intent.
+ *
+ * @param name The name of the desired item.
*
* @return the value of an item previously added with putExtra(),
* or null if no Parcelable[] value was found.
*
+ * @deprecated Use the type-safer {@link #getParcelableArrayExtra(String, Class)} starting from
+ * Android {@link Build.VERSION_CODES#TIRAMISU}.
+ *
* @see #putExtra(String, Parcelable[])
*/
+ @Deprecated
public @Nullable Parcelable[] getParcelableArrayExtra(String name) {
return mExtras == null ? null : mExtras.getParcelableArray(name);
}
@@ -8927,13 +8924,34 @@
* Retrieve extended data from the intent.
*
* @param name The name of the desired item.
+ * @param clazz The type of the items inside the array. This is only verified when unparceling.
+ *
+ * @return the value of an item previously added with putExtra(),
+ * or null if no Parcelable[] value was found.
+ *
+ * @see #putExtra(String, Parcelable[])
+ */
+ @SuppressLint({"ArrayReturn", "NullableCollection"})
+ public @Nullable <T> T[] getParcelableArrayExtra(@Nullable String name,
+ @NonNull Class<T> clazz) {
+ return mExtras == null ? null : mExtras.getParcelableArray(name, clazz);
+ }
+
+ /**
+ * Retrieve extended data from the intent.
+ *
+ * @param name The name of the desired item.
*
* @return the value of an item previously added with
* putParcelableArrayListExtra(), or null if no
* ArrayList<Parcelable> value was found.
*
+ * @deprecated Use the type-safer {@link #getParcelableArrayListExtra(String, Class)} starting
+ * from Android {@link Build.VERSION_CODES#TIRAMISU}.
+ *
* @see #putParcelableArrayListExtra(String, ArrayList)
*/
+ @Deprecated
public @Nullable <T extends Parcelable> ArrayList<T> getParcelableArrayListExtra(String name) {
return mExtras == null ? null : mExtras.<T>getParcelableArrayList(name);
}
@@ -8942,10 +8960,32 @@
* Retrieve extended data from the intent.
*
* @param name The name of the desired item.
+ * @param clazz The type of the items inside the array list. This is only verified when
+ * unparceling.
+ *
+ * @return the value of an item previously added with
+ * putParcelableArrayListExtra(), or null if no
+ * ArrayList<Parcelable> value was found.
+ *
+ * @see #putParcelableArrayListExtra(String, ArrayList)
+ */
+ @SuppressLint({"ConcreteCollection", "NullableCollection"})
+ public @Nullable <T> ArrayList<T> getParcelableArrayListExtra(@Nullable String name,
+ @NonNull Class<? extends T> clazz) {
+ return mExtras == null ? null : mExtras.<T>getParcelableArrayList(name, clazz);
+ }
+
+ /**
+ * Retrieve extended data from the intent.
+ *
+ * @param name The name of the desired item.
*
* @return the value of an item previously added with putExtra(),
* or null if no Serializable value was found.
*
+ * @deprecated Use the type-safer {@link #getSerializableExtra(String, Class)} starting from
+ * Android {@link Build.VERSION_CODES#TIRAMISU}.
+ *
* @see #putExtra(String, Serializable)
*/
public @Nullable Serializable getSerializableExtra(String name) {
@@ -8956,6 +8996,22 @@
* Retrieve extended data from the intent.
*
* @param name The name of the desired item.
+ * @param clazz The type of the object expected.
+ *
+ * @return the value of an item previously added with putExtra(),
+ * or null if no Serializable value was found.
+ *
+ * @see #putExtra(String, Serializable)
+ */
+ public @Nullable <T extends Serializable> T getSerializableExtra(@Nullable String name,
+ @NonNull Class<T> clazz) {
+ return mExtras == null ? null : mExtras.getSerializable(name, clazz);
+ }
+
+ /**
+ * Retrieve extended data from the intent.
+ *
+ * @param name The name of the desired item.
*
* @return the value of an item previously added with
* putIntegerArrayListExtra(), or null if no
diff --git a/core/java/android/content/pm/AppSearchShortcutInfo.java b/core/java/android/content/pm/AppSearchShortcutInfo.java
index f20d1e6..1b84686b 100644
--- a/core/java/android/content/pm/AppSearchShortcutInfo.java
+++ b/core/java/android/content/pm/AppSearchShortcutInfo.java
@@ -349,7 +349,7 @@
.setDisabledReason(shortcutInfo.getDisabledReason())
.setPersons(shortcutInfo.getPersons())
.setLocusId(shortcutInfo.getLocusId())
- .setCapabilityBindings(shortcutInfo.getCapabilityBindings())
+ .setCapabilityBindings(shortcutInfo.getCapabilityBindingsInternal())
.setTtlMillis(SHORTCUT_TTL)
.build();
}
diff --git a/media/java/android/media/tv/interactive/TvInteractiveAppInfo.aidl b/core/java/android/content/pm/Capability.aidl
similarity index 81%
copy from media/java/android/media/tv/interactive/TvInteractiveAppInfo.aidl
copy to core/java/android/content/pm/Capability.aidl
index 5e15016..df3b1be 100644
--- a/media/java/android/media/tv/interactive/TvInteractiveAppInfo.aidl
+++ b/core/java/android/content/pm/Capability.aidl
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2021 The Android Open Source Project
+ * Copyright (C) 2022 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -13,7 +13,6 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
+package android.content.pm;
-package android.media.tv.interactive;
-
-parcelable TvInteractiveAppInfo;
\ No newline at end of file
+parcelable Capability;
\ No newline at end of file
diff --git a/core/java/android/content/pm/Capability.java b/core/java/android/content/pm/Capability.java
new file mode 100644
index 0000000..1597d31
--- /dev/null
+++ b/core/java/android/content/pm/Capability.java
@@ -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 android.content.pm;
+
+import android.annotation.NonNull;
+import android.os.Parcel;
+import android.os.Parcelable;
+
+import java.util.Objects;
+
+/**
+ * Represents a capability that can be performed by an app, also known as App Action.
+ * Capabilities can be associated with a {@link ShortcutInfo}.
+ *
+ * @see ShortcutInfo.Builder#addCapabilityBinding(Capability, CapabilityParams)
+ */
+public final class Capability implements Parcelable {
+
+ @NonNull
+ private final String mName;
+
+ /**
+ * Constructor.
+ * @param name Name of the capability, usually maps to a built-in intent,
+ * e.g. actions.intent.GET_MESSAGE. Note the character "/" is not permitted.
+ * @throws IllegalArgumentException If specified capability name contains the character "/".
+ *
+ * @hide
+ */
+ Capability(@NonNull final String name) {
+ Objects.requireNonNull(name);
+ if (name.contains("/")) {
+ throw new IllegalArgumentException("'/' is not permitted in the capability name");
+ }
+ mName = name;
+ }
+
+ /**
+ * Copy constructor.
+ *
+ * @hide
+ */
+ Capability(@NonNull final Capability orig) {
+ this(orig.mName);
+ }
+
+ private Capability(@NonNull final Builder builder) {
+ this(builder.mName);
+ }
+
+ private Capability(@NonNull final Parcel in) {
+ mName = in.readString();
+ }
+
+ /**
+ * Returns the name of the capability. e.g. actions.intent.GET_MESSAGE.
+ */
+ @NonNull
+ public String getName() {
+ return mName;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (!(obj instanceof Capability)) {
+ return false;
+ }
+ return mName.equals(((Capability) obj).mName);
+ }
+
+ @Override
+ public int hashCode() {
+ return mName.hashCode();
+ }
+
+ @Override
+ public void writeToParcel(@NonNull Parcel dest, int flags) {
+ dest.writeString(mName);
+ }
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ @NonNull
+ public static final Parcelable.Creator<Capability> CREATOR =
+ new Parcelable.Creator<Capability>() {
+ @Override
+ public Capability[] newArray(int size) {
+ return new Capability[size];
+ }
+
+ @Override
+ public Capability createFromParcel(@NonNull Parcel in) {
+ return new Capability(in);
+ }
+ };
+
+ /**
+ * Builder class for {@link Capability}.
+ */
+ public static final class Builder {
+
+ @NonNull
+ private final String mName;
+
+ /**
+ * Constructor.
+ * @param name Name of the capability, usually maps to a built-in intent,
+ * e.g. actions.intent.GET_MESSAGE. Note the character "/" is not permitted.
+ * @throws IllegalArgumentException If specified capability name contains the character "/".
+ */
+ public Builder(@NonNull final String name) {
+ Objects.requireNonNull(name);
+ if (name.contains("/")) {
+ throw new IllegalArgumentException("'/' is not permitted in the capability name");
+ }
+ mName = name;
+ }
+
+ /**
+ * Creates an instance of {@link Capability}
+ */
+ @NonNull
+ public Capability build() {
+ return new Capability(this);
+ }
+ }
+}
diff --git a/media/java/android/media/tv/interactive/TvInteractiveAppInfo.aidl b/core/java/android/content/pm/CapabilityParams.aidl
similarity index 81%
copy from media/java/android/media/tv/interactive/TvInteractiveAppInfo.aidl
copy to core/java/android/content/pm/CapabilityParams.aidl
index 5e15016..39f1238 100644
--- a/media/java/android/media/tv/interactive/TvInteractiveAppInfo.aidl
+++ b/core/java/android/content/pm/CapabilityParams.aidl
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2021 The Android Open Source Project
+ * Copyright (C) 2022 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -13,7 +13,6 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
+package android.content.pm;
-package android.media.tv.interactive;
-
-parcelable TvInteractiveAppInfo;
\ No newline at end of file
+parcelable CapabilityParams;
diff --git a/core/java/android/content/pm/CapabilityParams.java b/core/java/android/content/pm/CapabilityParams.java
new file mode 100644
index 0000000..7239bac
--- /dev/null
+++ b/core/java/android/content/pm/CapabilityParams.java
@@ -0,0 +1,215 @@
+/*
+ * 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.content.pm;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.os.Parcel;
+import android.os.Parcelable;
+import android.text.TextUtils;
+import android.util.ArraySet;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.List;
+import java.util.Objects;
+import java.util.Set;
+
+/**
+ * Represents the parameters and its matching names which can be associated with a
+ * {@link Capability}.
+ *
+ * @see ShortcutInfo.Builder#addCapabilityBinding(Capability, CapabilityParams)
+ */
+public final class CapabilityParams implements Parcelable {
+
+ @NonNull
+ private final String mName;
+ @NonNull
+ private final String mPrimaryValue;
+ @NonNull
+ private final List<String> mAliases;
+
+ /**
+ * Constructor.
+ * @param name Name of the capability parameter.
+ * Note the character "/" is not permitted.
+ * @param primaryValue The primary value of the parameter.
+ * @param aliases Alternative values of the parameter.
+ */
+ private CapabilityParams(@NonNull final String name,
+ @NonNull final String primaryValue, @Nullable final Collection<String> aliases) {
+ Objects.requireNonNull(name);
+ Objects.requireNonNull(primaryValue);
+ mName = name;
+ mPrimaryValue = primaryValue;
+ mAliases = aliases == null ? Collections.emptyList()
+ : Collections.unmodifiableList(new ArrayList<>(aliases));
+ }
+
+ /**
+ * Copy constructor.
+ * @hide
+ */
+ CapabilityParams(@NonNull final CapabilityParams orig) {
+ this(orig.mName, orig.mPrimaryValue, orig.mAliases);
+ }
+
+ private CapabilityParams(@NonNull final Builder builder) {
+ this(builder.mKey, builder.mPrimaryValue, builder.mAliases);
+ }
+
+ private CapabilityParams(@NonNull final Parcel in) {
+ mName = in.readString();
+ mPrimaryValue = in.readString();
+ final List<String> values = new ArrayList<>();
+ in.readStringList(values);
+ mAliases = Collections.unmodifiableList(values);
+ }
+
+ /**
+ * Name of the parameter.
+ */
+ @NonNull
+ public String getName() {
+ return mName;
+ }
+
+ /**
+ * Returns the primary name of values in this parameter.
+ */
+ @NonNull
+ public String getValue() {
+ return mPrimaryValue;
+ }
+
+ /**
+ * Returns the aliases of the values in ths parameter. Returns an empty list if there are no
+ * aliases.
+ */
+ @NonNull
+ public List<String> getAliases() {
+ return new ArrayList<>(mAliases);
+ }
+
+ /**
+ * A list of values for this parameter. The first value will be the primary name, while the
+ * rest will be alternative names.
+ * @hide
+ */
+ @NonNull
+ List<String> getValues() {
+ if (mAliases == null) {
+ return new ArrayList<>(Collections.singletonList(mPrimaryValue));
+ }
+ final List<String> ret = new ArrayList<>(mAliases.size() + 1);
+ ret.add(mPrimaryValue);
+ ret.addAll(mAliases);
+ return ret;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (!(obj instanceof CapabilityParams)) {
+ return false;
+ }
+ final CapabilityParams target = (CapabilityParams) obj;
+ return mName.equals(target.mName) && mPrimaryValue.equals(target.mPrimaryValue)
+ && mAliases.equals(target.mAliases);
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(mName, mPrimaryValue, mAliases);
+ }
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ @Override
+ public void writeToParcel(@NonNull Parcel dest, int flags) {
+ dest.writeString(mName);
+ dest.writeString(mPrimaryValue);
+ dest.writeStringList(mAliases);
+ }
+
+ @NonNull
+ public static final Parcelable.Creator<CapabilityParams> CREATOR =
+ new Parcelable.Creator<CapabilityParams>() {
+ @Override
+ public CapabilityParams[] newArray(int size) {
+ return new CapabilityParams[size];
+ }
+
+ @Override
+ public CapabilityParams createFromParcel(@NonNull Parcel in) {
+ return new CapabilityParams(in);
+ }
+ };
+
+ /**
+ * Builder class for {@link CapabilityParams}.
+ */
+ public static final class Builder {
+
+ @NonNull
+ private final String mKey;
+ @NonNull
+ private String mPrimaryValue;
+ @NonNull
+ private Set<String> mAliases;
+
+ /**
+ * Constructor.
+ * @param key key of the capability parameter.
+ * Note the character "/" is not permitted.
+ * @param value The primary name of value in the {@link CapabilityParams}, cannot be empty.
+ */
+ public Builder(@NonNull final String key, @NonNull final String value) {
+ Objects.requireNonNull(key);
+ if (TextUtils.isEmpty(value)) {
+ throw new IllegalArgumentException("Primary value cannot be empty or null");
+ }
+ mPrimaryValue = value;
+ mKey = key;
+ }
+
+ /**
+ * Add an alias in the {@link CapabilityParams}.
+ */
+ @NonNull
+ public Builder addAlias(@NonNull final String alias) {
+ if (mAliases == null) {
+ mAliases = new ArraySet<>(1);
+ }
+ mAliases.add(alias);
+ return this;
+ }
+
+ /**
+ * Creates an instance of {@link CapabilityParams}
+ * @throws IllegalArgumentException If the specified value is empty.
+ */
+ @NonNull
+ public CapabilityParams build() {
+ return new CapabilityParams(this);
+ }
+ }
+}
diff --git a/core/java/android/content/pm/CrossProfileApps.java b/core/java/android/content/pm/CrossProfileApps.java
index 94f0561..66c6c81 100644
--- a/core/java/android/content/pm/CrossProfileApps.java
+++ b/core/java/android/content/pm/CrossProfileApps.java
@@ -104,7 +104,44 @@
mContext.getAttributionTag(),
component,
targetUser.getIdentifier(),
- true);
+ true,
+ null,
+ null);
+ } catch (RemoteException ex) {
+ throw ex.rethrowFromSystemServer();
+ }
+ }
+
+ /**
+ * Starts the specified main activity of the caller package in the specified profile, launching
+ * in the specified activity.
+ *
+ * @param component The ComponentName of the activity to launch, it must be exported and has
+ * action {@link android.content.Intent#ACTION_MAIN}, category
+ * {@link android.content.Intent#CATEGORY_LAUNCHER}. Otherwise, SecurityException will
+ * be thrown.
+ * @param targetUser The UserHandle of the profile, must be one of the users returned by
+ * {@link #getTargetUserProfiles()}, otherwise a {@link SecurityException} will
+ * be thrown.
+ * @param callingActivity The activity to start the new activity from for the purposes of
+ * deciding which task the new activity should belong to. If {@code null}, the activity
+ * will always be started in a new task.
+ * @param options The activity options or {@code null}. See {@link android.app.ActivityOptions}.
+ */
+ public void startMainActivity(@NonNull ComponentName component,
+ @NonNull UserHandle targetUser,
+ @Nullable Activity callingActivity,
+ @Nullable Bundle options) {
+ try {
+ mService.startActivityAsUser(
+ mContext.getIApplicationThread(),
+ mContext.getPackageName(),
+ mContext.getAttributionTag(),
+ component,
+ targetUser.getIdentifier(),
+ true,
+ callingActivity != null ? callingActivity.getActivityToken() : null,
+ options);
} catch (RemoteException ex) {
throw ex.rethrowFromSystemServer();
}
@@ -191,6 +228,48 @@
* @param targetUser The UserHandle of the profile, must be one of the users returned by
* {@link #getTargetUserProfiles()}, otherwise a {@link SecurityException} will
* be thrown.
+ * @param callingActivity The activity to start the new activity from for the purposes of
+ * deciding which task the new activity should belong to. If {@code null}, the activity
+ * will always be started in a new task.
+ * @param options The activity options or {@code null}. See {@link android.app.ActivityOptions}.
+ * @hide
+ */
+ @SystemApi
+ @RequiresPermission(anyOf = {
+ android.Manifest.permission.INTERACT_ACROSS_PROFILES,
+ android.Manifest.permission.START_CROSS_PROFILE_ACTIVITIES})
+ public void startActivity(
+ @NonNull ComponentName component,
+ @NonNull UserHandle targetUser,
+ @Nullable Activity callingActivity,
+ @Nullable Bundle options) {
+ try {
+ mService.startActivityAsUser(
+ mContext.getIApplicationThread(),
+ mContext.getPackageName(),
+ mContext.getAttributionTag(),
+ component,
+ targetUser.getIdentifier(),
+ false,
+ callingActivity != null ? callingActivity.getActivityToken() : null,
+ options);
+ } catch (RemoteException ex) {
+ throw ex.rethrowFromSystemServer();
+ }
+ }
+
+ /**
+ * Starts the specified activity of the caller package in the specified profile. Unlike
+ * {@link #startMainActivity}, this can start any activity of the caller package, not just
+ * the main activity.
+ * The caller must have the {@link android.Manifest.permission#INTERACT_ACROSS_PROFILES}
+ * or {@link android.Manifest.permission#START_CROSS_PROFILE_ACTIVITIES}
+ * permission and both the caller and target user profiles must be in the same profile group.
+ *
+ * @param component The ComponentName of the activity to launch. It must be exported.
+ * @param targetUser The UserHandle of the profile, must be one of the users returned by
+ * {@link #getTargetUserProfiles()}, otherwise a {@link SecurityException} will
+ * be thrown.
* @hide
*/
@SystemApi
@@ -201,7 +280,7 @@
try {
mService.startActivityAsUser(mContext.getIApplicationThread(),
mContext.getPackageName(), mContext.getAttributionTag(), component,
- targetUser.getIdentifier(), false);
+ targetUser.getIdentifier(), false, null, null);
} catch (RemoteException ex) {
throw ex.rethrowFromSystemServer();
}
@@ -247,7 +326,7 @@
final boolean isManagedProfile = mUserManager.isManagedProfile(userHandle.getIdentifier());
final DevicePolicyManager dpm = mContext.getSystemService(DevicePolicyManager.class);
- return dpm.getString(
+ return dpm.getResources().getString(
getUpdatableProfileSwitchingLabelId(isManagedProfile),
() -> getDefaultProfileSwitchingLabel(isManagedProfile));
}
diff --git a/core/java/android/content/pm/ICrossProfileApps.aidl b/core/java/android/content/pm/ICrossProfileApps.aidl
index e2850f1..4f2c106 100644
--- a/core/java/android/content/pm/ICrossProfileApps.aidl
+++ b/core/java/android/content/pm/ICrossProfileApps.aidl
@@ -29,7 +29,7 @@
interface ICrossProfileApps {
void startActivityAsUser(in IApplicationThread caller, in String callingPackage,
in String callingFeatureId, in ComponentName component, int userId,
- boolean launchMainActivity);
+ boolean launchMainActivity, in IBinder task, in Bundle options);
void startActivityAsUserByIntent(in IApplicationThread caller, in String callingPackage,
in String callingFeatureId, in Intent intent, int userId, in IBinder callingActivity,
in Bundle options);
diff --git a/core/java/android/content/pm/PackageInfo.java b/core/java/android/content/pm/PackageInfo.java
index eefa63f..f4de829 100644
--- a/core/java/android/content/pm/PackageInfo.java
+++ b/core/java/android/content/pm/PackageInfo.java
@@ -213,7 +213,8 @@
* or null if there were none. This is only filled in if the flag
* {@link PackageManager#GET_PERMISSIONS} was set. Each value matches
* the corresponding entry in {@link #requestedPermissions}, and will have
- * the flag {@link #REQUESTED_PERMISSION_GRANTED} set as appropriate.
+ * the flags {@link #REQUESTED_PERMISSION_GRANTED} and
+ * {@link #REQUESTED_PERMISSION_NEVER_FOR_LOCATION} set as appropriate.
*/
public int[] requestedPermissionsFlags;
diff --git a/core/java/android/content/pm/PackageManager.java b/core/java/android/content/pm/PackageManager.java
index 81c941e..6c62a2c 100644
--- a/core/java/android/content/pm/PackageManager.java
+++ b/core/java/android/content/pm/PackageManager.java
@@ -4087,6 +4087,28 @@
"android.software.incremental_delivery";
/**
+ * Feature for {@link #getSystemAvailableFeatures} and {@link #hasSystemFeature}: The device
+ * has the requisite kernel support for the EROFS filesystem present in 4.19 kernels as a
+ * staging driver, which lacks 0padding and big pcluster support.
+ *
+ * @hide
+ */
+ @SystemApi
+ @SdkConstant(SdkConstantType.FEATURE)
+ public static final String FEATURE_EROFS_LEGACY = "android.software.erofs_legacy";
+
+ /**
+ * Feature for {@link #getSystemAvailableFeatures} and {@link #hasSystemFeature}: The device
+ * has the requisite kernel support for the EROFS filesystem present in 5.10 kernels, which
+ * has 0padding, big pcluster, and chunked index support.
+ *
+ * @hide
+ */
+ @SystemApi
+ @SdkConstant(SdkConstantType.FEATURE)
+ public static final String FEATURE_EROFS = "android.software.erofs";
+
+ /**
* Feature for {@link #getSystemAvailableFeatures} and {@link #hasSystemFeature}:
* The device has tuner hardware to support tuner operations.
*
@@ -4970,8 +4992,8 @@
* applications (which includes installed applications as well as
* applications with data directory i.e. applications which had been
* deleted with {@code DELETE_KEEP_DATA} flag set).
- * @throws NameNotFoundException if a package with the given name cannot be
- * found on the system.
+ * @throws NameNotFoundException if no such package is available to the
+ * caller.
* @deprecated Use {@link #getPackageInfo(String, PackageInfoFlags)} instead.
*/
@Deprecated
@@ -5007,8 +5029,8 @@
* applications (which includes installed applications as well as
* applications with data directory i.e. applications which had been
* deleted with {@code DELETE_KEEP_DATA} flag set).
- * @throws NameNotFoundException if a package with the given name cannot be
- * found on the system.
+ * @throws NameNotFoundException if no such package is available to the
+ * caller.
* @deprecated Use {@link #getPackageInfo(VersionedPackage, PackageInfoFlags)} instead.
*/
@Deprecated
@@ -5040,8 +5062,8 @@
* applications (which includes installed applications as well as
* applications with data directory i.e. applications which had been
* deleted with {@code DELETE_KEEP_DATA} flag set).
- * @throws NameNotFoundException if a package with the given name cannot be
- * found on the system.
+ * @throws NameNotFoundException if no such package is available to the
+ * caller.
* @deprecated Use {@link #getPackageInfoAsUser(String, PackageInfoFlags, int)} instead.
* @hide
*/
@@ -5166,8 +5188,8 @@
* desired package.
* @return Returns an int array of the assigned GIDs, or null if there are
* none.
- * @throws NameNotFoundException if a package with the given name cannot be
- * found on the system.
+ * @throws NameNotFoundException if no such package is available to the
+ * caller.
*/
public abstract int[] getPackageGids(@NonNull String packageName)
throws NameNotFoundException;
@@ -5183,8 +5205,8 @@
* desired package.
* @return Returns an int array of the assigned gids, or null if there are
* none.
- * @throws NameNotFoundException if a package with the given name cannot be
- * found on the system.
+ * @throws NameNotFoundException if no such package is available to the
+ * caller.
* @deprecated Use {@link #getPackageGids(String, PackageInfoFlags)} instead.
*/
@Deprecated
@@ -5210,8 +5232,8 @@
* @param packageName The full name (i.e. com.google.apps.contacts) of the
* desired package.
* @return Returns an integer UID who owns the given package name.
- * @throws NameNotFoundException if a package with the given name can not be
- * found on the system.
+ * @throws NameNotFoundException if no such package is available to the
+ * caller.
* @deprecated Use {@link #getPackageUid(String, PackageInfoFlags)} instead.
*/
@Deprecated
@@ -5237,8 +5259,8 @@
* desired package.
* @param userId The user handle identifier to look up the package under.
* @return Returns an integer UID who owns the given package name.
- * @throws NameNotFoundException if a package with the given name can not be
- * found on the system.
+ * @throws NameNotFoundException if no such package is available to the
+ * caller.
* @hide
*/
@SuppressWarnings("HiddenAbstractMethod")
@@ -5256,8 +5278,8 @@
* desired package.
* @param userId The user handle identifier to look up the package under.
* @return Returns an integer UID who owns the given package name.
- * @throws NameNotFoundException if a package with the given name can not be
- * found on the system.
+ * @throws NameNotFoundException if no such package is available to the
+ * caller.
* @deprecated Use {@link #getPackageUidAsUser(String, PackageInfoFlags, int)} instead.
* @hide
*/
diff --git a/core/java/android/content/pm/SHORTCUT_OWNERS b/core/java/android/content/pm/SHORTCUT_OWNERS
index 3688d5a..f8bba473 100644
--- a/core/java/android/content/pm/SHORTCUT_OWNERS
+++ b/core/java/android/content/pm/SHORTCUT_OWNERS
@@ -1,7 +1,6 @@
set noparent
+pinyaoting@google.com
+sunnygoyal@google.com
omakoto@google.com
yamasani@google.com
-sunnygoyal@google.com
-mett@google.com
-pinyaoting@google.com
diff --git a/core/java/android/content/pm/ShortcutInfo.java b/core/java/android/content/pm/ShortcutInfo.java
index 41dd5bb3..56d092d 100644
--- a/core/java/android/content/pm/ShortcutInfo.java
+++ b/core/java/android/content/pm/ShortcutInfo.java
@@ -52,7 +52,7 @@
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
-import java.util.Collection;
+import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
@@ -60,7 +60,6 @@
import java.util.Objects;
import java.util.Set;
import java.util.stream.Collectors;
-import java.util.stream.Stream;
/**
* Represents a shortcut that can be published via {@link ShortcutManager}.
@@ -501,7 +500,8 @@
mRank = b.mRank;
mExtras = b.mExtras;
mLocusId = b.mLocusId;
- mCapabilityBindings = b.mCapabilityBindings;
+ mCapabilityBindings =
+ cloneCapabilityBindings(b.mCapabilityBindings);
mStartingThemeResName = b.mStartingThemeResId != 0
? b.mContext.getResources().getResourceName(b.mStartingThemeResId) : null;
updateTimestamp();
@@ -652,7 +652,8 @@
// Set this bit.
mFlags |= FLAG_KEY_FIELDS_ONLY;
}
- mCapabilityBindings = source.mCapabilityBindings;
+ mCapabilityBindings = cloneCapabilityBindings(
+ source.mCapabilityBindings);
mStartingThemeResName = source.mStartingThemeResName;
}
@@ -1003,7 +1004,8 @@
mStartingThemeResName = source.mStartingThemeResName;
}
if (source.mCapabilityBindings != null) {
- mCapabilityBindings = source.mCapabilityBindings;
+ mCapabilityBindings =
+ cloneCapabilityBindings(source.mCapabilityBindings);
}
}
@@ -1447,43 +1449,25 @@
* <P>This method can be called multiple times to add multiple parameters to the same
* capability.
*
- * @param capability capability associated with the shortcut. e.g. actions.intent
- * .START_EXERCISE.
- * @param parameterName name of the parameter associated with given capability.
- * e.g. exercise.name.
- * @param parameterValues a list of values for that parameters. The first value will be
- * the primary name, while the rest will be alternative names. If
- * the values are empty, then the parameter will not be saved in
- * the shortcut.
+ * @param capability {@link Capability} associated with the shortcut.
+ * @param capabilityParams Optional {@link CapabilityParams} associated with given
+ * capability.
*/
@NonNull
- public Builder addCapabilityBinding(@NonNull String capability,
- @Nullable String parameterName, @Nullable List<String> parameterValues) {
+ public Builder addCapabilityBinding(@NonNull final Capability capability,
+ @Nullable final CapabilityParams capabilityParams) {
Objects.requireNonNull(capability);
- if (capability.contains("/")) {
- throw new IllegalArgumentException("Illegal character '/' is found in capability");
- }
if (mCapabilityBindings == null) {
mCapabilityBindings = new ArrayMap<>(1);
}
- if (!mCapabilityBindings.containsKey(capability)) {
- mCapabilityBindings.put(capability, new ArrayMap<>(0));
+ if (!mCapabilityBindings.containsKey(capability.getName())) {
+ mCapabilityBindings.put(capability.getName(), new ArrayMap<>(0));
}
- if (parameterName == null || parameterValues == null || parameterValues.isEmpty()) {
+ if (capabilityParams == null) {
return this;
}
- if (parameterName.contains("/")) {
- throw new IllegalArgumentException(
- "Illegal character '/' is found in parameter name");
- }
- final Map<String, List<String>> params = mCapabilityBindings.get(capability);
- if (!params.containsKey(parameterName)) {
- params.put(parameterName, parameterValues);
- return this;
- }
- params.put(parameterName,
- Stream.of(params.get(parameterName), parameterValues)
- .flatMap(Collection::stream).collect(Collectors.toList()));
+ final Map<String, List<String>> params = mCapabilityBindings.get(capability.getName());
+ params.put(capabilityParams.getName(), capabilityParams.getValues());
return this;
}
@@ -2264,41 +2248,78 @@
}
/**
+ * Returns an immutable copy of the capability bindings using internal data structure.
* @hide
*/
- public Map<String, Map<String, List<String>>> getCapabilityBindings() {
- return mCapabilityBindings;
+ @Nullable
+ public Map<String, Map<String, List<String>>> getCapabilityBindingsInternal() {
+ return cloneCapabilityBindings(mCapabilityBindings);
+ }
+
+ @Nullable
+ private static Map<String, Map<String, List<String>>> cloneCapabilityBindings(
+ @Nullable final Map<String, Map<String, List<String>>> orig) {
+ if (orig == null) {
+ return null;
+ }
+ final Map<String, Map<String, List<String>>> ret = new ArrayMap<>();
+ for (String capability : orig.keySet()) {
+ final Map<String, List<String>> params = orig.get(capability);
+ final Map<String, List<String>> clone;
+ if (params == null) {
+ clone = null;
+ } else {
+ clone = new ArrayMap<>(params.size());
+ for (String paramName : params.keySet()) {
+ final List<String> paramValues = params.get(paramName);
+ clone.put(paramName, Collections.unmodifiableList(paramValues));
+ }
+ }
+ ret.put(capability, Collections.unmodifiableMap(clone));
+ }
+ return Collections.unmodifiableMap(ret);
}
/**
- * Return true if the shortcut is or can be used in specified capability.
- */
- public boolean hasCapability(@NonNull String capability) {
- Objects.requireNonNull(capability);
- return mCapabilityBindings != null && mCapabilityBindings.containsKey(capability);
- }
-
- /**
- * Returns the values of specified parameter in associated with given capability.
- *
- * @param capability capability associated with the shortcut. e.g. actions.intent
- * .START_EXERCISE.
- * @param parameterName name of the parameter associated with given capability.
- * e.g. exercise.name.
+ * Return a list of {@link Capability} associated with the shortcut.
*/
@NonNull
- public List<String> getCapabilityParameterValues(
- @NonNull String capability, @NonNull String parameterName) {
- Objects.requireNonNull(capability);
- Objects.requireNonNull(parameterName);
+ public List<Capability> getCapabilities() {
if (mCapabilityBindings == null) {
- return Collections.emptyList();
+ return new ArrayList<>(0);
}
- final Map<String, List<String>> param = mCapabilityBindings.get(capability);
- if (param == null || !param.containsKey(parameterName)) {
- return Collections.emptyList();
+ return mCapabilityBindings.keySet().stream().map(Capability::new)
+ .collect(Collectors.toList());
+ }
+
+ /**
+ * Returns the {@link CapabilityParams} in associated with given capability.
+ *
+ * @param capability {@link Capability} associated with the shortcut.
+ */
+ @NonNull
+ public List<CapabilityParams> getCapabilityParams(@NonNull final Capability capability) {
+ Objects.requireNonNull(capability);
+ if (mCapabilityBindings == null) {
+ return new ArrayList<>(0);
}
- return param.get(parameterName);
+ final Map<String, List<String>> param = mCapabilityBindings.get(capability.getName());
+ if (param == null) {
+ return new ArrayList<>(0);
+ }
+ final List<CapabilityParams> ret = new ArrayList<>(param.size());
+ for (String key : param.keySet()) {
+ final List<String> values = param.get(key);
+ final String primaryValue = values.get(0);
+ final List<String> aliases = values.size() == 1
+ ? Collections.emptyList() : values.subList(1, values.size());
+ CapabilityParams.Builder builder = new CapabilityParams.Builder(key, primaryValue);
+ for (String alias : aliases) {
+ builder = builder.addAlias(alias);
+ }
+ ret.add(builder.build());
+ }
+ return ret;
}
private ShortcutInfo(Parcel source) {
@@ -2357,7 +2378,7 @@
final Map<String, Map<String, List<String>>> capabilityBindings =
new ArrayMap<>(rawCapabilityBindings.size());
rawCapabilityBindings.forEach(capabilityBindings::put);
- mCapabilityBindings = capabilityBindings;
+ mCapabilityBindings = cloneCapabilityBindings(capabilityBindings);
}
}
@@ -2695,6 +2716,6 @@
mPersons = persons;
mLocusId = locusId;
mStartingThemeResName = startingThemeResName;
- mCapabilityBindings = capabilityBindings;
+ mCapabilityBindings = cloneCapabilityBindings(capabilityBindings);
}
}
diff --git a/core/java/android/content/pm/SigningInfo.java b/core/java/android/content/pm/SigningInfo.java
index 7459a90..ee9aaca3 100644
--- a/core/java/android/content/pm/SigningInfo.java
+++ b/core/java/android/content/pm/SigningInfo.java
@@ -72,9 +72,11 @@
/**
* Returns the signing certificates this package has proven it is authorized to use. This
* includes both the signing certificate associated with the signer of the package and the past
- * signing certificates it included as its proof of signing certificate rotation. This method
- * is the preferred replacement for the {@code GET_SIGNATURES} flag used with {@link
- * PackageManager#getPackageInfo(String, int)}. When determining if a package is signed by a
+ * signing certificates it included as its proof of signing certificate rotation. Signing
+ * certificates are returned in the order of rotation with the original signing certificate at
+ * index 0, and the current signing certificate at the last index. This method is the preferred
+ * replacement for the {@code GET_SIGNATURES} flag used with {@link
+ * PackageManager#getPackageInfo(String, int)}. When determining if a package is signed by a
* desired certificate, the returned array should be checked to determine if it is one of the
* entries.
*
diff --git a/core/java/android/content/res/AssetManager.java b/core/java/android/content/res/AssetManager.java
index a05f5c9..c8bbb0c1 100644
--- a/core/java/android/content/res/AssetManager.java
+++ b/core/java/android/content/res/AssetManager.java
@@ -79,6 +79,13 @@
@GuardedBy("sSync") private static ArraySet<ApkAssets> sSystemApkAssetsSet;
/**
+ * Cookie value to use when the actual cookie is unknown. This value tells the system to search
+ * all the ApkAssets for the asset.
+ * @hide
+ */
+ public static final int COOKIE_UNKNOWN = -1;
+
+ /**
* Mode for {@link #open(String, int)}: no specific information about how
* data will be accessed.
*/
diff --git a/core/java/android/hardware/CameraStreamStats.java b/core/java/android/hardware/CameraStreamStats.java
index 7b24cc4..3952467 100644
--- a/core/java/android/hardware/CameraStreamStats.java
+++ b/core/java/android/hardware/CameraStreamStats.java
@@ -49,7 +49,7 @@
private float[] mHistogramBins;
private long[] mHistogramCounts;
private long mDynamicRangeProfile;
- private int mStreamUseCase;
+ private long mStreamUseCase;
private static final String TAG = "CameraStreamStats";
@@ -73,7 +73,7 @@
public CameraStreamStats(int width, int height, int format, float maxPreviewFps,
int dataSpace, long usage, long requestCount, long errorCount,
int startLatencyMs, int maxHalBuffers, int maxAppBuffers, long dynamicRangeProfile,
- int streamUseCase) {
+ long streamUseCase) {
mWidth = width;
mHeight = height;
mFormat = format;
@@ -135,7 +135,7 @@
dest.writeFloatArray(mHistogramBins);
dest.writeLongArray(mHistogramCounts);
dest.writeLong(mDynamicRangeProfile);
- dest.writeInt(mStreamUseCase);
+ dest.writeLong(mStreamUseCase);
}
public void readFromParcel(Parcel in) {
@@ -154,7 +154,7 @@
mHistogramBins = in.createFloatArray();
mHistogramCounts = in.createLongArray();
mDynamicRangeProfile = in.readLong();
- mStreamUseCase = in.readInt();
+ mStreamUseCase = in.readLong();
}
public int getWidth() {
@@ -217,7 +217,7 @@
return mDynamicRangeProfile;
}
- public int getStreamUseCase() {
+ public long getStreamUseCase() {
return mStreamUseCase;
}
}
diff --git a/core/java/android/hardware/SyncFence.java b/core/java/android/hardware/SyncFence.java
index cd4bf78..1660013 100644
--- a/core/java/android/hardware/SyncFence.java
+++ b/core/java/android/hardware/SyncFence.java
@@ -24,6 +24,7 @@
import android.os.Parcel;
import android.os.ParcelFileDescriptor;
import android.os.Parcelable;
+import android.os.SystemClock;
import libcore.util.NativeAllocationRegistry;
@@ -105,6 +106,21 @@
}
}
+ /**
+ * Creates a SyncFence from a libui Fence*
+ * DOES NOT TAKE AN ADDITIONAL REFERENCE, the caller must incref if it intends to retain
+ * ownership (eg, when using sp<Fence>)
+ * @hide
+ */
+ public SyncFence(long nativeFencePtr) {
+ mNativePtr = nativeFencePtr;
+ if (nativeFencePtr != 0) {
+ mCloser = sRegistry.registerNativeAllocation(this, mNativePtr);
+ } else {
+ mCloser = () -> {};
+ }
+ }
+
private SyncFence() {
mCloser = () -> {};
}
@@ -194,7 +210,9 @@
}
/**
- * Returns the time that the fence signaled in the CLOCK_MONOTONIC time domain.
+ * Returns the time in nanoseconds that the fence signaled in the CLOCK_MONOTONIC time domain.
+ * This corresponds to {@link System#nanoTime()} but may also be compared to
+ * {@link SystemClock#uptimeMillis()} after adjusting for milliseconds vs. nanoseconds.
*
* If the fence isn't valid, that is if {@link #isValid()} is false, then this returns
* {@link #SIGNAL_TIME_INVALID}. Similarly, if an error occurs while trying to access the
diff --git a/core/java/android/hardware/camera2/CameraCharacteristics.java b/core/java/android/hardware/camera2/CameraCharacteristics.java
index 7bebe1f..b05e6d1 100644
--- a/core/java/android/hardware/camera2/CameraCharacteristics.java
+++ b/core/java/android/hardware/camera2/CameraCharacteristics.java
@@ -3563,8 +3563,8 @@
*/
@PublicKey
@NonNull
- public static final Key<int[]> SCALER_AVAILABLE_STREAM_USE_CASES =
- new Key<int[]>("android.scaler.availableStreamUseCases", int[].class);
+ public static final Key<long[]> SCALER_AVAILABLE_STREAM_USE_CASES =
+ new Key<long[]>("android.scaler.availableStreamUseCases", long[].class);
/**
* <p>An array of mandatory stream combinations with stream use cases.
diff --git a/core/java/android/hardware/camera2/params/MandatoryStreamCombination.java b/core/java/android/hardware/camera2/params/MandatoryStreamCombination.java
index 465abfb..a3bc665 100644
--- a/core/java/android/hardware/camera2/params/MandatoryStreamCombination.java
+++ b/core/java/android/hardware/camera2/params/MandatoryStreamCombination.java
@@ -66,7 +66,7 @@
private final boolean mIsUltraHighResolution;
private final boolean mIsMaximumSize;
private final boolean mIs10BitCapable;
- private final int mStreamUseCase;
+ private final long mStreamUseCase;
/**
* Create a new {@link MandatoryStreamInformation}.
@@ -168,7 +168,7 @@
*/
public MandatoryStreamInformation(@NonNull List<Size> availableSizes, @Format int format,
boolean isMaximumSize, boolean isInput, boolean isUltraHighResolution,
- boolean is10BitCapable, @StreamUseCase int streamUseCase) {
+ boolean is10BitCapable, @StreamUseCase long streamUseCase) {
if (availableSizes.isEmpty()) {
throw new IllegalArgumentException("No available sizes");
}
@@ -308,9 +308,9 @@
* For {@link MandatoryStreamInformation} belonging to other mandatory stream
* combinations, the return value will be DEFAULT. </p>
*
- * @return the integer stream use case.
+ * @return the long integer stream use case.
*/
- public @StreamUseCase int getStreamUseCase() {
+ public @StreamUseCase long getStreamUseCase() {
return mStreamUseCase;
}
@@ -365,15 +365,15 @@
/**
* Short hand for stream use cases
*/
- private static final int STREAM_USE_CASE_PREVIEW =
+ private static final long STREAM_USE_CASE_PREVIEW =
CameraMetadata.SCALER_AVAILABLE_STREAM_USE_CASES_PREVIEW;
- private static final int STREAM_USE_CASE_STILL_CAPTURE =
+ private static final long STREAM_USE_CASE_STILL_CAPTURE =
CameraMetadata.SCALER_AVAILABLE_STREAM_USE_CASES_STILL_CAPTURE;
- private static final int STREAM_USE_CASE_RECORD =
+ private static final long STREAM_USE_CASE_RECORD =
CameraMetadata.SCALER_AVAILABLE_STREAM_USE_CASES_VIDEO_RECORD;
- private static final int STREAM_USE_CASE_PREVIEW_VIDEO_STILL =
+ private static final long STREAM_USE_CASE_PREVIEW_VIDEO_STILL =
CameraMetadata.SCALER_AVAILABLE_STREAM_USE_CASES_PREVIEW_VIDEO_STILL;
- private static final int STREAM_USE_CASE_VIDEO_CALL =
+ private static final long STREAM_USE_CASE_VIDEO_CALL =
CameraMetadata.SCALER_AVAILABLE_STREAM_USE_CASES_VIDEO_CALL;
/**
@@ -471,12 +471,12 @@
private static final class StreamTemplate {
public int mFormat;
public SizeThreshold mSizeThreshold;
- public int mStreamUseCase;
+ public long mStreamUseCase;
public StreamTemplate(int format, SizeThreshold sizeThreshold) {
this(format, sizeThreshold, CameraMetadata.SCALER_AVAILABLE_STREAM_USE_CASES_DEFAULT);
}
public StreamTemplate(@Format int format, @NonNull SizeThreshold sizeThreshold,
- @StreamUseCase int streamUseCase) {
+ @StreamUseCase long streamUseCase) {
mFormat = format;
mSizeThreshold = sizeThreshold;
mStreamUseCase = streamUseCase;
diff --git a/core/java/android/hardware/camera2/params/OutputConfiguration.java b/core/java/android/hardware/camera2/params/OutputConfiguration.java
index 2350b7c..39cb7f3 100644
--- a/core/java/android/hardware/camera2/params/OutputConfiguration.java
+++ b/core/java/android/hardware/camera2/params/OutputConfiguration.java
@@ -918,9 +918,9 @@
* @throws IllegalArgumentException If the streamUseCase isn't within the range of valid
* values.
*/
- public void setStreamUseCase(@StreamUseCase int streamUseCase) {
+ public void setStreamUseCase(@StreamUseCase long streamUseCase) {
// Verify that the value is in range
- int maxUseCaseValue = CameraMetadata.SCALER_AVAILABLE_STREAM_USE_CASES_VIDEO_CALL;
+ long maxUseCaseValue = CameraMetadata.SCALER_AVAILABLE_STREAM_USE_CASES_VIDEO_CALL;
if (streamUseCase > maxUseCaseValue &&
streamUseCase < CameraMetadata.SCALER_AVAILABLE_STREAM_USE_CASES_VENDOR_START) {
throw new IllegalArgumentException("Not a valid stream use case value " +
@@ -938,7 +938,7 @@
*
* @return the currently set stream use case
*/
- public int getStreamUseCase() {
+ public long getStreamUseCase() {
return mStreamUseCase;
}
@@ -1067,7 +1067,7 @@
String physicalCameraId = source.readString();
boolean isMultiResolutionOutput = source.readInt() == 1;
int[] sensorPixelModesUsed = source.createIntArray();
- int streamUseCase = source.readInt();
+ long streamUseCase = source.readLong();
checkArgumentInRange(rotation, ROTATION_0, ROTATION_270, "Rotation constant");
long dynamicRangeProfile = source.readLong();
@@ -1218,7 +1218,7 @@
// writeList doesn't seem to work well with Integer list.
dest.writeIntArray(convertIntegerToIntList(mSensorPixelModesUsed));
dest.writeLong(mDynamicRangeProfile);
- dest.writeInt(mStreamUseCase);
+ dest.writeLong(mStreamUseCase);
dest.writeInt(mTimestampBase);
dest.writeInt(mMirrorMode);
}
@@ -1337,7 +1337,7 @@
// Dynamic range profile
private long mDynamicRangeProfile;
// Stream use case
- private int mStreamUseCase;
+ private long mStreamUseCase;
// Timestamp base
private int mTimestampBase;
// Mirroring mode
diff --git a/core/java/android/hardware/fingerprint/FingerprintManager.java b/core/java/android/hardware/fingerprint/FingerprintManager.java
index 7e070bc..29221b8 100644
--- a/core/java/android/hardware/fingerprint/FingerprintManager.java
+++ b/core/java/android/hardware/fingerprint/FingerprintManager.java
@@ -923,14 +923,15 @@
* @hide
*/
@RequiresPermission(USE_BIOMETRIC_INTERNAL)
- public void onPointerDown(int sensorId, int x, int y, float minor, float major) {
+ public void onPointerDown(long requestId, int sensorId, int x, int y,
+ float minor, float major) {
if (mService == null) {
Slog.w(TAG, "onFingerDown: no fingerprint service");
return;
}
try {
- mService.onPointerDown(sensorId, x, y, minor, major);
+ mService.onPointerDown(requestId, sensorId, x, y, minor, major);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
@@ -940,14 +941,14 @@
* @hide
*/
@RequiresPermission(USE_BIOMETRIC_INTERNAL)
- public void onPointerUp(int sensorId) {
+ public void onPointerUp(long requestId, int sensorId) {
if (mService == null) {
Slog.w(TAG, "onFingerDown: no fingerprint service");
return;
}
try {
- mService.onPointerUp(sensorId);
+ mService.onPointerUp(requestId, sensorId);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
@@ -957,14 +958,14 @@
* @hide
*/
@RequiresPermission(USE_BIOMETRIC_INTERNAL)
- public void onUiReady(int sensorId) {
+ public void onUiReady(long requestId, int sensorId) {
if (mService == null) {
Slog.w(TAG, "onUiReady: no fingerprint service");
return;
}
try {
- mService.onUiReady(sensorId);
+ mService.onUiReady(requestId, sensorId);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
diff --git a/core/java/android/hardware/fingerprint/IFingerprintService.aidl b/core/java/android/hardware/fingerprint/IFingerprintService.aidl
index cbff8b1..12114aa 100644
--- a/core/java/android/hardware/fingerprint/IFingerprintService.aidl
+++ b/core/java/android/hardware/fingerprint/IFingerprintService.aidl
@@ -155,13 +155,13 @@
void addAuthenticatorsRegisteredCallback(IFingerprintAuthenticatorsRegisteredCallback callback);
// Notifies about a finger touching the sensor area.
- void onPointerDown(int sensorId, int x, int y, float minor, float major);
+ void onPointerDown(long requestId, int sensorId, int x, int y, float minor, float major);
// Notifies about a finger leaving the sensor area.
- void onPointerUp(int sensorId);
+ void onPointerUp(long requestId, int sensorId);
// Notifies about the fingerprint UI being ready (e.g. HBM illumination is enabled).
- void onUiReady(int sensorId);
+ void onUiReady(long requestId, int sensorId);
// Sets the controller for managing the UDFPS overlay.
void setUdfpsOverlayController(in IUdfpsOverlayController controller);
diff --git a/core/java/android/hardware/fingerprint/IUdfpsOverlayController.aidl b/core/java/android/hardware/fingerprint/IUdfpsOverlayController.aidl
index 3cca1b3..dbb8e40 100644
--- a/core/java/android/hardware/fingerprint/IUdfpsOverlayController.aidl
+++ b/core/java/android/hardware/fingerprint/IUdfpsOverlayController.aidl
@@ -23,7 +23,7 @@
*/
oneway interface IUdfpsOverlayController {
// Shows the overlay for the given sensor with a reason from BiometricOverlayConstants.
- void showUdfpsOverlay(int sensorId, int reason, IUdfpsOverlayControllerCallback callback);
+ void showUdfpsOverlay(long requestId, int sensorId, int reason, IUdfpsOverlayControllerCallback callback);
// Hides the overlay.
void hideUdfpsOverlay(int sensorId);
diff --git a/core/java/android/inputmethodservice/NavigationBarController.java b/core/java/android/inputmethodservice/NavigationBarController.java
index 0f9075b..03d1151 100644
--- a/core/java/android/inputmethodservice/NavigationBarController.java
+++ b/core/java/android/inputmethodservice/NavigationBarController.java
@@ -294,8 +294,8 @@
dest.setTouchableInsets(
ViewTreeObserver.InternalInsetsInfo.TOUCHABLE_INSETS_REGION);
- // TODO(b/205803355): See if we can use View#OnLayoutChangeListener().
- // TODO(b/205803355): See if we can replace DecorView#mNavigationColorViewState.view
+ // TODO(b/215443343): See if we can use View#OnLayoutChangeListener().
+ // TODO(b/215443343): See if we can replace DecorView#mNavigationColorViewState.view
boolean zOrderChanged = false;
if (decor instanceof ViewGroup) {
ViewGroup decorGroup = (ViewGroup) decor;
diff --git a/core/java/android/inputmethodservice/navigationbar/DeadZone.java b/core/java/android/inputmethodservice/navigationbar/DeadZone.java
index 4cfd813..382b6b0 100644
--- a/core/java/android/inputmethodservice/navigationbar/DeadZone.java
+++ b/core/java/android/inputmethodservice/navigationbar/DeadZone.java
@@ -148,7 +148,7 @@
if (DEBUG) {
Log.v(TAG, this + " ACTION_DOWN: " + event.getX() + "," + event.getY());
}
- //TODO(b/205803355): call mNavBarController.touchAutoDim(mDisplayId); here
+ //TODO(b/215443343): call mNavBarController.touchAutoDim(mDisplayId); here
int size = (int) getSize(event.getEventTime());
// In the vertical orientation consume taps along the left edge.
// In horizontal orientation consume taps along the top edge.
diff --git a/core/java/android/inputmethodservice/navigationbar/KeyButtonView.java b/core/java/android/inputmethodservice/navigationbar/KeyButtonView.java
index cfdb6ca..92d358f 100644
--- a/core/java/android/inputmethodservice/navigationbar/KeyButtonView.java
+++ b/core/java/android/inputmethodservice/navigationbar/KeyButtonView.java
@@ -89,7 +89,7 @@
public KeyButtonView(Context context, AttributeSet attrs) {
super(context, attrs);
- // TODO(b/205803355): Figure out better place to set this.
+ // TODO(b/215443343): Figure out better place to set this.
switch (getId()) {
case com.android.internal.R.id.input_method_nav_back:
mCode = KEYCODE_BACK;
@@ -285,11 +285,11 @@
private void sendEvent(int action, int flags, long when) {
if (mCode == KeyEvent.KEYCODE_BACK && flags != KeyEvent.FLAG_LONG_PRESS) {
if (action == MotionEvent.ACTION_UP) {
- // TODO(b/205803355): Implement notifyBackAction();
+ // TODO(b/215443343): Implement notifyBackAction();
}
}
- // TODO(b/205803355): Consolidate this logic to somewhere else.
+ // TODO(b/215443343): Consolidate this logic to somewhere else.
if (mContext instanceof InputMethodService) {
final int repeatCount = (flags & KeyEvent.FLAG_LONG_PRESS) != 0 ? 1 : 0;
final KeyEvent ev = new KeyEvent(mDownTime, when, action, mCode, repeatCount,
diff --git a/core/java/android/net/IVpnManager.aidl b/core/java/android/net/IVpnManager.aidl
index 070efa3..b4647ca 100644
--- a/core/java/android/net/IVpnManager.aidl
+++ b/core/java/android/net/IVpnManager.aidl
@@ -17,6 +17,7 @@
package android.net;
import android.net.Network;
+import android.net.VpnProfileState;
import com.android.internal.net.LegacyVpnInfo;
import com.android.internal.net.VpnConfig;
@@ -40,6 +41,7 @@
void deleteVpnProfile(String packageName);
String startVpnProfile(String packageName);
void stopVpnProfile(String packageName);
+ VpnProfileState getProvisionedVpnProfileState(String packageName);
/** Always-on VPN APIs */
boolean isAlwaysOnVpnPackageSupported(int userId, String packageName);
diff --git a/core/java/android/net/Ikev2VpnProfile.java b/core/java/android/net/Ikev2VpnProfile.java
index 0fd3e03..3abe83b 100644
--- a/core/java/android/net/Ikev2VpnProfile.java
+++ b/core/java/android/net/Ikev2VpnProfile.java
@@ -142,6 +142,7 @@
private final boolean mIsMetered; // Defaults in builder
private final int mMaxMtu; // Defaults in builder
private final boolean mIsRestrictedToTestNetworks;
+ @Nullable private final IkeTunnelConnectionParams mIkeTunConnParams;
private Ikev2VpnProfile(
int type,
@@ -160,7 +161,8 @@
int maxMtu,
boolean restrictToTestNetworks,
boolean excludeLocalRoutes,
- boolean requiresInternetValidation) {
+ boolean requiresInternetValidation,
+ @Nullable IkeTunnelConnectionParams ikeTunConnParams) {
super(type, excludeLocalRoutes, requiresInternetValidation);
checkNotNull(serverAddr, MISSING_PARAM_MSG_TMPL, "Server address");
@@ -190,6 +192,8 @@
mMaxMtu = maxMtu;
mIsRestrictedToTestNetworks = restrictToTestNetworks;
+ mIkeTunConnParams = ikeTunConnParams;
+
validate();
}
@@ -375,6 +379,12 @@
return mMaxMtu;
}
+ /** Retrieves the ikeTunnelConnectionParams contains IKEv2 configurations, if any was set. */
+ @Nullable
+ public IkeTunnelConnectionParams getIkeTunnelConnectionParams() {
+ return mIkeTunConnParams;
+ }
+
/**
* Returns whether or not this VPN profile is restricted to test networks.
*
@@ -403,7 +413,8 @@
mMaxMtu,
mIsRestrictedToTestNetworks,
mExcludeLocalRoutes,
- mRequiresInternetValidation);
+ mRequiresInternetValidation,
+ mIkeTunConnParams);
}
@Override
@@ -429,7 +440,8 @@
&& mMaxMtu == other.mMaxMtu
&& mIsRestrictedToTestNetworks == other.mIsRestrictedToTestNetworks
&& mExcludeLocalRoutes == other.mExcludeLocalRoutes
- && mRequiresInternetValidation == other.mRequiresInternetValidation;
+ && mRequiresInternetValidation == other.mRequiresInternetValidation
+ && Objects.equals(mIkeTunConnParams, other.mIkeTunConnParams);
}
/**
@@ -504,6 +516,7 @@
@NonNull
public static Ikev2VpnProfile fromVpnProfile(@NonNull VpnProfile profile)
throws GeneralSecurityException {
+ // TODO: Build the VpnProfile from mIkeTunConnParams if it exists.
final Builder builder = new Builder(profile.server, profile.ipsecIdentifier);
builder.setProxy(profile.proxy);
builder.setAllowedAlgorithms(profile.getAllowedAlgorithms());
@@ -788,7 +801,7 @@
private int mMaxMtu = PlatformVpnProfile.MAX_MTU_DEFAULT;
private boolean mIsRestrictedToTestNetworks = false;
private boolean mExcludeLocalRoutes = false;
- @Nullable private IkeTunnelConnectionParams mIkeTunConnParams;
+ @Nullable private final IkeTunnelConnectionParams mIkeTunConnParams;
/**
* Creates a new builder with the basic parameters of an IKEv2/IPsec VPN.
@@ -803,6 +816,8 @@
mServerAddr = serverAddr;
mUserIdentity = identity;
+
+ mIkeTunConnParams = null;
}
/**
@@ -1135,7 +1150,8 @@
mMaxMtu,
mIsRestrictedToTestNetworks,
mExcludeLocalRoutes,
- mRequiresInternetValidation);
+ mRequiresInternetValidation,
+ mIkeTunConnParams);
}
}
}
diff --git a/core/java/android/net/NetworkPolicyManager.java b/core/java/android/net/NetworkPolicyManager.java
index 18ec8f5..2c2a703 100644
--- a/core/java/android/net/NetworkPolicyManager.java
+++ b/core/java/android/net/NetworkPolicyManager.java
@@ -580,6 +580,24 @@
}
/**
+ * Notifies that the specified {@link NetworkStatsProvider} has reached its warning threshold
+ * which was set through {@link NetworkStatsProvider#onSetWarningAndLimit(String, long, long)}.
+ *
+ * @hide
+ */
+ @RequiresPermission(anyOf = {
+ NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK,
+ android.Manifest.permission.NETWORK_STACK})
+ @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES)
+ public void notifyStatsProviderWarningReached() {
+ try {
+ mService.notifyStatsProviderWarningOrLimitReached();
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+
+ /**
* Notifies that the specified {@link NetworkStatsProvider} has reached its quota
* which was set through {@link NetworkStatsProvider#onSetLimit(String, long)} or
* {@link NetworkStatsProvider#onSetWarningAndLimit(String, long, long)}.
@@ -590,7 +608,7 @@
NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK,
android.Manifest.permission.NETWORK_STACK})
@SystemApi(client = SystemApi.Client.MODULE_LIBRARIES)
- public void notifyStatsProviderWarningOrLimitReached() {
+ public void notifyStatsProviderLimitReached() {
try {
mService.notifyStatsProviderWarningOrLimitReached();
} catch (RemoteException e) {
diff --git a/core/java/android/net/SntpClient.java b/core/java/android/net/SntpClient.java
index 0eb4cf3..b05f7cf 100644
--- a/core/java/android/net/SntpClient.java
+++ b/core/java/android/net/SntpClient.java
@@ -60,7 +60,7 @@
private static final int TRANSMIT_TIME_OFFSET = 40;
private static final int NTP_PACKET_SIZE = 48;
- private static final int NTP_PORT = 123;
+ public static final int STANDARD_NTP_PORT = 123;
private static final int NTP_MODE_CLIENT = 3;
private static final int NTP_MODE_SERVER = 4;
private static final int NTP_MODE_BROADCAST = 5;
@@ -108,18 +108,21 @@
* Sends an SNTP request to the given host and processes the response.
*
* @param host host name of the server.
+ * @param port port of the server.
* @param timeout network timeout in milliseconds. the timeout doesn't include the DNS lookup
* time, and it applies to each individual query to the resolved addresses of
* the NTP server.
* @param network network over which to send the request.
* @return true if the transaction was successful.
*/
- public boolean requestTime(String host, int timeout, Network network) {
+ public boolean requestTime(String host, int port, int timeout, Network network) {
final Network networkForResolv = network.getPrivateDnsBypassingCopy();
try {
final InetAddress[] addresses = networkForResolv.getAllByName(host);
for (int i = 0; i < addresses.length; i++) {
- if (requestTime(addresses[i], NTP_PORT, timeout, networkForResolv)) return true;
+ if (requestTime(addresses[i], port, timeout, networkForResolv)) {
+ return true;
+ }
}
} catch (UnknownHostException e) {
Log.w(TAG, "Unknown host: " + host);
diff --git a/core/java/android/net/VpnManager.java b/core/java/android/net/VpnManager.java
index c51444c..ae7d91f 100644
--- a/core/java/android/net/VpnManager.java
+++ b/core/java/android/net/VpnManager.java
@@ -161,6 +161,23 @@
"android.net.category.EVENT_DEACTIVATED_BY_USER";
/**
+ * The always-on state of this VPN was changed
+ *
+ * <p>This may be the result of a user changing VPN settings, or a Device Policy Manager app
+ * having changed the VPN policy.
+ */
+ @SdkConstant(SdkConstant.SdkConstantType.INTENT_CATEGORY)
+ public static final String CATEGORY_EVENT_ALWAYS_ON_STATE_CHANGED =
+ "android.net.category.EVENT_ALWAYS_ON_STATE_CHANGED";
+
+ /**
+ * The VpnProfileState at the time that this event occurred.
+ *
+ * <p>This extra may be null if the VPN was revoked by the user, or the profile was deleted.
+ */
+ public static final String EXTRA_VPN_PROFILE_STATE = "android.net.extra.VPN_PROFILE_STATE";
+
+ /**
* The key of the session that experienced this event, as a {@code String}.
*
* This is the same key that was returned by {@link #startProvisionedVpnProfileSession}.
@@ -403,6 +420,21 @@
}
/**
+ * Retrieve the VpnProfileState for the profile provisioned by the calling package.
+ *
+ * @return the VpnProfileState with current information, or null if there was no profile
+ * provisioned by the calling package.
+ */
+ @Nullable
+ public VpnProfileState getProvisionedVpnProfileState() {
+ try {
+ return mService.getProvisionedVpnProfileState(mContext.getOpPackageName());
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+
+ /**
* Resets all VPN settings back to factory defaults.
* @hide
*/
diff --git a/media/java/android/media/tv/interactive/TvInteractiveAppInfo.aidl b/core/java/android/net/VpnProfileState.aidl
similarity index 81%
copy from media/java/android/media/tv/interactive/TvInteractiveAppInfo.aidl
copy to core/java/android/net/VpnProfileState.aidl
index 5e15016..add6386e 100644
--- a/media/java/android/media/tv/interactive/TvInteractiveAppInfo.aidl
+++ b/core/java/android/net/VpnProfileState.aidl
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2021 The Android Open Source Project
+ * Copyright (C) 2022 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -14,6 +14,6 @@
* limitations under the License.
*/
-package android.media.tv.interactive;
+package android.net;
-parcelable TvInteractiveAppInfo;
\ No newline at end of file
+parcelable VpnProfileState;
\ No newline at end of file
diff --git a/core/java/android/net/VpnProfileState.java b/core/java/android/net/VpnProfileState.java
new file mode 100644
index 0000000..c69ea1a
--- /dev/null
+++ b/core/java/android/net/VpnProfileState.java
@@ -0,0 +1,153 @@
+/*
+ * 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.net;
+
+import android.annotation.IntDef;
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.os.Parcel;
+import android.os.Parcelable;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+
+/**
+ * Describe the state of VPN.
+ */
+public final class VpnProfileState implements Parcelable {
+ /** The VPN has not been started, or some other VPN is active. */
+ public static final int STATE_DISCONNECTED = 0;
+ /** The VPN is attempting to connect, potentially after a failure. */
+ public static final int STATE_CONNECTING = 1;
+ /** The VPN was established successfully. */
+ public static final int STATE_CONNECTED = 2;
+ /** A non-recoverable error has occurred, and will not be retried. */
+ public static final int STATE_FAILED = 3;
+ /** @hide */
+ @Retention(RetentionPolicy.SOURCE)
+ @IntDef(prefix = {"STATE_"}, value = {
+ STATE_CONNECTED,
+ STATE_CONNECTING,
+ STATE_DISCONNECTED,
+ STATE_FAILED,
+ })
+ public @interface State {}
+
+ @State private final int mState;
+ private final String mSessionKey;
+ private final boolean mAlwaysOn;
+ private final boolean mLockdown;
+
+ public VpnProfileState(@State int state, @Nullable String sessionKey, boolean alwaysOn,
+ boolean lockdown) {
+ mState = state;
+ mSessionKey = sessionKey;
+ mAlwaysOn = alwaysOn;
+ mLockdown = lockdown;
+ }
+
+ /**
+ * Returns the state of the Platform VPN
+ *
+ * <p>This state represents the internal connection state of the VPN. This state may diverge
+ * from the VPN Network's state during error and recovery handling.
+ */
+ @State public int getState() {
+ return mState;
+ }
+
+ /**
+ * Retrieves the Session Key
+ *
+ * <p>The session key is an ephemeral key uniquely identifying the session for a Platform VPN.
+ * The lifetime of this key is tied to the lifetime of the VPN session. In other words,
+ * reprovisioning of the VPN profile, restarting of the device, or manually restarting the
+ * platform VPN session will result in a new VPN session, and a new key.
+ *
+ * @return the unique key for the platform VPN session, or null if it is not running.
+ */
+ @Nullable
+ public String getSessionId() {
+ return mSessionKey;
+ }
+
+ /**
+ * Returns the always-on status of the PlatformVpnProfile.
+ *
+ * <p>If the PlatformVpnProfile is set to be running in always-on mode, the system will ensure
+ * that the profile is always started, and restarting it when necessary (e.g. after reboot).
+ *
+ * <p>Always-on can be set by an appropriately privileged user via the Settings VPN menus, or by
+ * the Device Policy Manager app programmatically.
+ *
+ * See DevicePolicyManager#setAlwaysOnVpnPackage(ComponentName, String, boolean, Set)
+ */
+ public boolean isAlwaysOn() {
+ return mAlwaysOn;
+ }
+
+ /**
+ * Returns the lockdown mode status of the PlatformVpnProfile.
+ *
+ * <p>In lockdown mode, the system will ensure that apps are not allowed to bypass the VPN,
+ * including during startup or failure of the VPN.
+ *
+ * <p>Lockdown mode can be set by an appropriately privileged user via the Settings VPN menus,
+ * or by the Device Policy Manager app programmatically.
+ *
+ * See DevicePolicyManager#setAlwaysOnVpnPackage(ComponentName, String, boolean, Set)
+ */
+ public boolean isLockdownEnabled() {
+ return mLockdown;
+ }
+
+ /**
+ * Implement the Parcelable interface
+ */
+ public int describeContents() {
+ return 0;
+ }
+
+ /**
+ * Implement the Parcelable interface
+ */
+ public void writeToParcel(@NonNull Parcel out, int flags) {
+ out.writeInt(mState);
+ out.writeString(mSessionKey);
+ out.writeBoolean(mAlwaysOn);
+ out.writeBoolean(mLockdown);
+ }
+
+ @NonNull
+ public static final Parcelable.Creator<VpnProfileState> CREATOR =
+ new Parcelable.Creator<VpnProfileState>() {
+ public VpnProfileState createFromParcel(Parcel in) {
+ return new VpnProfileState(in);
+ }
+
+ public VpnProfileState[] newArray(int size) {
+ return new VpnProfileState[size];
+ }
+ };
+
+ private VpnProfileState(Parcel in) {
+ mState = in.readInt();
+ mSessionKey = in.readString();
+ mAlwaysOn = in.readBoolean();
+ mLockdown = in.readBoolean();
+ }
+}
diff --git a/core/java/android/net/netstats/NetworkStatsDataMigrationUtils.java b/core/java/android/net/netstats/NetworkStatsDataMigrationUtils.java
index 2dd3aaa1..5c9989e 100644
--- a/core/java/android/net/netstats/NetworkStatsDataMigrationUtils.java
+++ b/core/java/android/net/netstats/NetworkStatsDataMigrationUtils.java
@@ -27,6 +27,7 @@
import static android.telephony.SubscriptionManager.INVALID_SUBSCRIPTION_ID;
import android.annotation.NonNull;
+import android.annotation.StringDef;
import android.annotation.SystemApi;
import android.net.NetworkIdentity;
import android.net.NetworkStatsCollection;
@@ -47,6 +48,8 @@
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
import java.net.ProtocolException;
import java.util.ArrayList;
import java.util.HashMap;
@@ -76,6 +79,15 @@
*/
public static final String PREFIX_UID_TAG = "uid_tag";
+ /** @hide */
+ @StringDef(prefix = {"PREFIX_"}, value = {
+ PREFIX_XT,
+ PREFIX_UID,
+ PREFIX_UID_TAG,
+ })
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface Prefix {}
+
private static final HashMap<String, String> sPrefixLegacyFileNameMap =
new HashMap<String, String>() {{
put(PREFIX_XT, "netstats_xt.bin");
@@ -141,13 +153,13 @@
// Get /data/system/netstats_*.bin legacy files. Does not check for existence.
@NonNull
- private static File getLegacyBinFileForPrefix(@NonNull String prefix) {
+ private static File getLegacyBinFileForPrefix(@NonNull @Prefix String prefix) {
return new File(getPlatformSystemDir(), sPrefixLegacyFileNameMap.get(prefix));
}
// List /data/system/netstats/[xt|uid|uid_tag].<start>-<end> legacy files.
@NonNull
- private static ArrayList<File> getPlatformFileListForPrefix(@NonNull String prefix) {
+ private static ArrayList<File> getPlatformFileListForPrefix(@NonNull @Prefix String prefix) {
final ArrayList<File> list = new ArrayList<>();
final File platformFiles = new File(getPlatformBaseDir(), "netstats");
if (platformFiles.exists()) {
@@ -207,7 +219,7 @@
*/
@NonNull
public static NetworkStatsCollection readPlatformCollection(
- @NonNull String prefix, long bucketDuration) throws IOException {
+ @NonNull @Prefix String prefix, long bucketDuration) throws IOException {
final NetworkStatsCollection.Builder builder =
new NetworkStatsCollection.Builder(bucketDuration);
diff --git a/core/java/android/os/BatteryConsumer.java b/core/java/android/os/BatteryConsumer.java
index de76c8f..f4ca1b5 100644
--- a/core/java/android/os/BatteryConsumer.java
+++ b/core/java/android/os/BatteryConsumer.java
@@ -165,6 +165,7 @@
PROCESS_STATE_FOREGROUND,
PROCESS_STATE_BACKGROUND,
PROCESS_STATE_FOREGROUND_SERVICE,
+ PROCESS_STATE_CACHED,
})
@Retention(RetentionPolicy.SOURCE)
public @interface ProcessState {
@@ -175,8 +176,9 @@
public static final int PROCESS_STATE_FOREGROUND = 1;
public static final int PROCESS_STATE_BACKGROUND = 2;
public static final int PROCESS_STATE_FOREGROUND_SERVICE = 3;
+ public static final int PROCESS_STATE_CACHED = 4;
- public static final int PROCESS_STATE_COUNT = 4;
+ public static final int PROCESS_STATE_COUNT = 5;
private static final String[] sProcessStateNames = new String[PROCESS_STATE_COUNT];
@@ -186,6 +188,7 @@
sProcessStateNames[PROCESS_STATE_FOREGROUND] = "fg";
sProcessStateNames[PROCESS_STATE_BACKGROUND] = "bg";
sProcessStateNames[PROCESS_STATE_FOREGROUND_SERVICE] = "fgs";
+ sProcessStateNames[PROCESS_STATE_CACHED] = "cached";
}
private static final int[] SUPPORTED_POWER_COMPONENTS_PER_PROCESS_STATE = {
diff --git a/core/java/android/os/BatteryStats.java b/core/java/android/os/BatteryStats.java
index 5f9fdbf..06c35b5 100644
--- a/core/java/android/os/BatteryStats.java
+++ b/core/java/android/os/BatteryStats.java
@@ -680,6 +680,8 @@
return BatteryConsumer.PROCESS_STATE_BACKGROUND;
case BatteryStats.Uid.PROCESS_STATE_FOREGROUND_SERVICE:
return BatteryConsumer.PROCESS_STATE_FOREGROUND_SERVICE;
+ case BatteryStats.Uid.PROCESS_STATE_CACHED:
+ return BatteryConsumer.PROCESS_STATE_CACHED;
default:
return BatteryConsumer.PROCESS_STATE_UNSPECIFIED;
}
@@ -2681,7 +2683,7 @@
public static final String[] RADIO_ACCESS_TECHNOLOGY_NAMES = {"Other", "LTE", "NR"};
/**
- * Returns the time in microseconds that the mobile radio has been active on a
+ * Returns the time in milliseconds that the mobile radio has been active on a
* given Radio Access Technology (RAT), at a given frequency (NR RAT only), for a given
* transmission power level.
*
@@ -2700,6 +2702,46 @@
@ServiceState.FrequencyRange int frequencyRange, int signalStrength,
long elapsedRealtimeMs);
+ /**
+ * Returns the time in milliseconds that the mobile radio has been actively transmitting data on
+ * a given Radio Access Technology (RAT), at a given frequency (NR RAT only), for a given
+ * transmission power level.
+ *
+ * @param rat Radio Access Technology {@see RadioAccessTechnology}
+ * @param frequencyRange frequency range {@see ServiceState.FrequencyRange}, only needed for
+ * RADIO_ACCESS_TECHNOLOGY_NR. Use
+ * {@link ServiceState.FREQUENCY_RANGE_UNKNOWN} for other Radio Access
+ * Technologies.
+ * @param signalStrength the cellular signal strength. {@see CellSignalStrength#getLevel()}
+ * @param elapsedRealtimeMs current elapsed realtime
+ * @return time (in milliseconds) the mobile radio spent actively transmitting data in the
+ * specified state, while on battery. Returns {@link DURATION_UNAVAILABLE} if
+ * data unavailable.
+ * @hide
+ */
+ public abstract long getActiveTxRadioDurationMs(@RadioAccessTechnology int rat,
+ @ServiceState.FrequencyRange int frequencyRange, int signalStrength,
+ long elapsedRealtimeMs);
+
+ /**
+ * Returns the time in milliseconds that the mobile radio has been actively receiving data on a
+ * given Radio Access Technology (RAT), at a given frequency (NR RAT only), for a given
+ * transmission power level.
+ *
+ * @param rat Radio Access Technology {@see RadioAccessTechnology}
+ * @param frequencyRange frequency range {@see ServiceState.FrequencyRange}, only needed for
+ * RADIO_ACCESS_TECHNOLOGY_NR. Use
+ * {@link ServiceState.FREQUENCY_RANGE_UNKNOWN} for other Radio Access
+ * Technologies.
+ * @param elapsedRealtimeMs current elapsed realtime
+ * @return time (in milliseconds) the mobile radio spent actively receiving data in the
+ * specified state, while on battery. Returns {@link DURATION_UNAVAILABLE} if
+ * data unavailable.
+ * @hide
+ */
+ public abstract long getActiveRxRadioDurationMs(@RadioAccessTechnology int rat,
+ @ServiceState.FrequencyRange int frequencyRange, long elapsedRealtimeMs);
+
static final String[] WIFI_SUPPL_STATE_NAMES = {
"invalid", "disconn", "disabled", "inactive", "scanning",
"authenticating", "associating", "associated", "4-way-handshake",
@@ -2720,6 +2762,13 @@
public static final long POWER_DATA_UNAVAILABLE = -1L;
/**
+ * Returned value if duration data is unavailable.
+ *
+ * {@hide}
+ */
+ public static final long DURATION_UNAVAILABLE = -1L;
+
+ /**
* Returns the battery consumption (in microcoulombs) of bluetooth, derived from on
* device power measurement data.
* Will return {@link #POWER_DATA_UNAVAILABLE} if data is unavailable.
@@ -4093,6 +4142,10 @@
" Mmwave frequency (greater than 6GHz):\n"};
final String signalStrengthHeader =
" Signal Strength Time:\n";
+ final String txHeader =
+ " Tx Time:\n";
+ final String rxHeader =
+ " Rx Time: ";
final String[] signalStrengthDescription = new String[]{
" unknown: ",
" poor: ",
@@ -4144,6 +4197,29 @@
sb.append(")\n");
}
+ sb.append(prefix);
+ sb.append(txHeader);
+ for (int strength = 0; strength < numSignalStrength; strength++) {
+ final long timeMs = getActiveTxRadioDurationMs(rat, freqLvl, strength,
+ rawRealtimeMs);
+ if (timeMs <= 0) continue;
+ hasFreqData = true;
+ sb.append(prefix);
+ sb.append(signalStrengthDescription[strength]);
+ formatTimeMs(sb, timeMs);
+ sb.append("(");
+ sb.append(formatRatioLocked(timeMs, totalActiveTimesMs));
+ sb.append(")\n");
+ }
+
+ sb.append(prefix);
+ sb.append(rxHeader);
+ final long rxTimeMs = getActiveRxRadioDurationMs(rat, freqLvl, rawRealtimeMs);
+ formatTimeMs(sb, rxTimeMs);
+ sb.append("(");
+ sb.append(formatRatioLocked(rxTimeMs, totalActiveTimesMs));
+ sb.append(")\n");
+
if (hasFreqData) {
hasData = true;
pw.print(sb);
diff --git a/core/java/android/os/IpcDataCache.java b/core/java/android/os/IpcDataCache.java
index 00734c80..0efa34c 100644
--- a/core/java/android/os/IpcDataCache.java
+++ b/core/java/android/os/IpcDataCache.java
@@ -16,12 +16,12 @@
package android.os;
-import android.app.PropertyInvalidatedCache;
-import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
+import android.annotation.StringDef;
import android.annotation.SystemApi;
import android.annotation.TestApi;
+import android.app.PropertyInvalidatedCache;
import android.text.TextUtils;
import android.util.Log;
@@ -267,6 +267,25 @@
};
/**
+ * The list of cache namespaces. Each namespace corresponds to an sepolicy domain. A
+ * namespace is owned by a single process, although a single process can have more
+ * than one namespace (system_server, as an example).
+ * @hide
+ */
+ @StringDef(
+ prefix = { "MODULE_"
+ },
+ value = {
+ MODULE_TEST,
+ MODULE_SYSTEM,
+ MODULE_BLUETOOTH,
+ MODULE_TELEPHONY
+ }
+ )
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface IpcDataCacheModule { }
+
+ /**
* The module used for unit tests and cts tests. It is expected that no process in
* the system has permissions to write properties with this module.
* @hide
@@ -304,7 +323,8 @@
*/
@SystemApi(client=SystemApi.Client.MODULE_LIBRARIES)
@TestApi
- public IpcDataCache(int maxEntries, @NonNull String module, @NonNull String api,
+ public IpcDataCache(int maxEntries, @NonNull @IpcDataCacheModule String module,
+ @NonNull String api,
@NonNull String cacheName, @NonNull QueryHandler<Query, Result> computer) {
super(maxEntries, module, api, cacheName, computer);
}
@@ -358,7 +378,8 @@
*/
@SystemApi(client=SystemApi.Client.MODULE_LIBRARIES)
@TestApi
- public static void invalidateCache(@NonNull String module, @NonNull String api) {
+ public static void invalidateCache(@NonNull @IpcDataCacheModule String module,
+ @NonNull String api) {
PropertyInvalidatedCache.invalidateCache(module, api);
}
}
diff --git a/core/java/android/os/ParcelableHolder.java b/core/java/android/os/ParcelableHolder.java
index 368ee2d..a739ba3 100644
--- a/core/java/android/os/ParcelableHolder.java
+++ b/core/java/android/os/ParcelableHolder.java
@@ -179,7 +179,11 @@
* Read ParcelableHolder from a parcel.
*/
public void readFromParcel(@NonNull Parcel parcel) {
- this.mStability = parcel.readInt();
+ int wireStability = parcel.readInt();
+ if (this.mStability != wireStability) {
+ throw new IllegalArgumentException("Expected stability " + this.mStability
+ + " but got " + wireStability);
+ }
mParcelable = null;
diff --git a/core/java/android/os/PowerComponents.java b/core/java/android/os/PowerComponents.java
index 6051712..522807b 100644
--- a/core/java/android/os/PowerComponents.java
+++ b/core/java/android/os/PowerComponents.java
@@ -292,6 +292,10 @@
procState = BatteryUsageStatsAtomsProto.BatteryConsumerData.PowerComponentUsageSlice
.FOREGROUND_SERVICE;
break;
+ case BatteryConsumer.PROCESS_STATE_CACHED:
+ procState = BatteryUsageStatsAtomsProto.BatteryConsumerData.PowerComponentUsageSlice
+ .CACHED;
+ break;
default:
throw new IllegalArgumentException("Unknown process state: " + processState);
}
diff --git a/core/java/android/os/UidBatteryConsumer.java b/core/java/android/os/UidBatteryConsumer.java
index 77d1498..91d231e 100644
--- a/core/java/android/os/UidBatteryConsumer.java
+++ b/core/java/android/os/UidBatteryConsumer.java
@@ -119,6 +119,8 @@
skipEmptyComponents);
appendProcessStateData(sb, BatteryConsumer.PROCESS_STATE_FOREGROUND_SERVICE,
skipEmptyComponents);
+ appendProcessStateData(sb, BatteryConsumer.PROCESS_STATE_CACHED,
+ skipEmptyComponents);
pw.print(sb);
}
diff --git a/core/java/android/os/UserManager.java b/core/java/android/os/UserManager.java
index 276578e..608c424 100644
--- a/core/java/android/os/UserManager.java
+++ b/core/java/android/os/UserManager.java
@@ -17,7 +17,7 @@
package android.os;
import static android.app.admin.DevicePolicyResources.Strings.Core.WORK_PROFILE_BADGED_LABEL;
-import static android.app.admin.DevicePolicyResources.Strings.UNDEFINED;
+import static android.app.admin.DevicePolicyResources.UNDEFINED;
import android.Manifest;
import android.accounts.AccountManager;
@@ -1703,12 +1703,40 @@
/**
* A response code from {@link #removeUserWhenPossible(UserHandle, boolean)} indicating that
- * an error occurred that prevented the user from being removed or set as ephemeral.
+ * an unknown error occurred that prevented the user from being removed or set as ephemeral.
*
* @hide
*/
@SystemApi
- public static final int REMOVE_RESULT_ERROR = 3;
+ public static final int REMOVE_RESULT_ERROR_UNKNOWN = -1;
+
+ /**
+ * A response code from {@link #removeUserWhenPossible(UserHandle, boolean)} indicating that
+ * the user could not be removed due to a {@link #DISALLOW_REMOVE_MANAGED_PROFILE} or
+ * {@link #DISALLOW_REMOVE_USER} user restriction.
+ *
+ * @hide
+ */
+ @SystemApi
+ public static final int REMOVE_RESULT_ERROR_USER_RESTRICTION = -2;
+
+ /**
+ * A response code from {@link #removeUserWhenPossible(UserHandle, boolean)} indicating that
+ * user being removed does not exist.
+ *
+ * @hide
+ */
+ @SystemApi
+ public static final int REMOVE_RESULT_ERROR_USER_NOT_FOUND = -3;
+
+ /**
+ * A response code from {@link #removeUserWhenPossible(UserHandle, boolean)} indicating that
+ * user being removed is a {@link UserHandle#SYSTEM} user which can't be removed.
+ *
+ * @hide
+ */
+ @SystemApi
+ public static final int REMOVE_RESULT_ERROR_SYSTEM_USER = -4;
/**
* Possible response codes from {@link #removeUserWhenPossible(UserHandle, boolean)}.
@@ -1719,7 +1747,10 @@
REMOVE_RESULT_REMOVED,
REMOVE_RESULT_DEFERRED,
REMOVE_RESULT_ALREADY_BEING_REMOVED,
- REMOVE_RESULT_ERROR,
+ REMOVE_RESULT_ERROR_USER_RESTRICTION,
+ REMOVE_RESULT_ERROR_USER_NOT_FOUND,
+ REMOVE_RESULT_ERROR_SYSTEM_USER,
+ REMOVE_RESULT_ERROR_UNKNOWN,
})
@Retention(RetentionPolicy.SOURCE)
public @interface RemoveResult {}
@@ -4718,7 +4749,7 @@
return label;
}
DevicePolicyManager dpm = mContext.getSystemService(DevicePolicyManager.class);
- return dpm.getString(
+ return dpm.getResources().getString(
getUpdatableUserBadgedLabelId(userId),
() -> getDefaultUserBadgedLabel(label, userId),
/* formatArgs= */ label);
@@ -4846,8 +4877,10 @@
* the {@link #DISALLOW_REMOVE_USER} or {@link #DISALLOW_REMOVE_MANAGED_PROFILE} restriction
*
* @return the {@link RemoveResult} code: {@link #REMOVE_RESULT_REMOVED},
- * {@link #REMOVE_RESULT_DEFERRED}, {@link #REMOVE_RESULT_ALREADY_BEING_REMOVED}, or
- * {@link #REMOVE_RESULT_ERROR}.
+ * {@link #REMOVE_RESULT_DEFERRED}, {@link #REMOVE_RESULT_ALREADY_BEING_REMOVED},
+ * {@link #REMOVE_RESULT_ERROR_USER_RESTRICTION}, {@link #REMOVE_RESULT_ERROR_USER_NOT_FOUND},
+ * {@link #REMOVE_RESULT_ERROR_SYSTEM_USER}, or {@link #REMOVE_RESULT_ERROR_UNKNOWN}. All error
+ * codes have negative values.
*
* @hide
*/
@@ -4864,6 +4897,19 @@
}
/**
+ * Check if {@link #removeUserWhenPossible} returned a success code which means that the user
+ * has been removed or is slated for removal.
+ *
+ * @param result is {@link #RemoveResult} code return by {@link #removeUserWhenPossible}.
+ * @return {@code true} if it is a success code.
+ * @hide
+ */
+ @SystemApi
+ public static boolean isRemoveResultSuccessful(@RemoveResult int result) {
+ return result >= 0;
+ }
+
+ /**
* Updates the user's name.
*
* @param userId the user's integer id
diff --git a/core/java/android/os/storage/IStorageManager.aidl b/core/java/android/os/storage/IStorageManager.aidl
index 7832dcc..a0f6598 100644
--- a/core/java/android/os/storage/IStorageManager.aidl
+++ b/core/java/android/os/storage/IStorageManager.aidl
@@ -78,37 +78,10 @@
*/
String getMountedObbPath(in String rawPath) = 24;
/**
- * Decrypts any encrypted volumes.
- */
- int decryptStorage(in String password) = 26;
- /**
- * Encrypts storage.
- */
- int encryptStorage(int type, in String password) = 27;
- /**
- * Changes the encryption password.
- */
- int changeEncryptionPassword(int type, in String password) = 28;
- /**
* Returns list of all mountable volumes for the specified userId
*/
StorageVolume[] getVolumeList(int userId, in String callingPackage, int flags) = 29;
/**
- * Determines the encryption state of the volume.
- * @return a numerical value. See {@code ENCRYPTION_STATE_*} for possible
- * values.
- * Note that this has been replaced in most cases by the APIs in
- * StorageManager (see isEncryptable and below)
- * This is still useful to get the error state when encryption has failed
- * and CryptKeeper needs to throw up a screen advising the user what to do
- */
- int getEncryptionState() = 31;
- /**
- * Verify the encryption password against the stored volume. This method
- * may only be called by the system process.
- */
- int verifyEncryptionPassword(in String password) = 32;
- /**
* Ensure that all directories along given path exist, creating parent
* directories as needed. Validates that given path is absolute and that it
* contains no relative "." or ".." paths or symlinks. Also ensures that
@@ -117,32 +90,6 @@
*/
void mkdirs(in String callingPkg, in String path) = 34;
/**
- * Determines the type of the encryption password
- * @return PasswordType
- */
- int getPasswordType() = 35;
- /**
- * Get password from vold
- * @return password or empty string
- */
- String getPassword() = 36;
- /**
- * Securely clear password from vold
- */
- oneway void clearPassword() = 37;
- /**
- * Set a field in the crypto header.
- * @param field field to set
- * @param contents contents to set in field
- */
- oneway void setField(in String field, in String contents) = 38;
- /**
- * Gets a field from the crypto header.
- * @param field field to get
- * @return contents of field
- */
- String getField(in String field) = 39;
- /**
* Report the time of the last maintenance operation such as fstrim.
* @return Timestamp of the last maintenance operation, in the
* System.currentTimeMillis() time base
@@ -178,7 +125,6 @@
boolean isUserKeyUnlocked(int userId) = 65;
void prepareUserStorage(in String volumeUuid, int userId, int serialNumber, int flags) = 66;
void destroyUserStorage(in String volumeUuid, int userId, int flags) = 67;
- boolean isConvertibleToFBE() = 68;
void addUserKeyAuth(int userId, int serialNumber, in byte[] secret) = 70;
void fixateNewestUserKeyAuth(int userId) = 71;
void fstrim(int flags, IVoldTaskListener listener) = 72;
diff --git a/core/java/android/os/storage/StorageManager.java b/core/java/android/os/storage/StorageManager.java
index 312abf8..9971cbc 100644
--- a/core/java/android/os/storage/StorageManager.java
+++ b/core/java/android/os/storage/StorageManager.java
@@ -3044,14 +3044,4 @@
public static final int CRYPT_TYPE_PATTERN = IVold.PASSWORD_TYPE_PATTERN;
/** @hide */
public static final int CRYPT_TYPE_PIN = IVold.PASSWORD_TYPE_PIN;
-
- // Constants for the data available via StorageManagerService.getField.
- /** @hide */
- public static final String SYSTEM_LOCALE_KEY = "SystemLocale";
- /** @hide */
- public static final String OWNER_INFO_KEY = "OwnerInfo";
- /** @hide */
- public static final String PATTERN_VISIBLE_KEY = "PatternVisible";
- /** @hide */
- public static final String PASSWORD_VISIBLE_KEY = "PasswordVisible";
}
diff --git a/core/java/android/permission/IPermissionController.aidl b/core/java/android/permission/IPermissionController.aidl
index c9dd06c..e3f02e7 100644
--- a/core/java/android/permission/IPermissionController.aidl
+++ b/core/java/android/permission/IPermissionController.aidl
@@ -59,6 +59,6 @@
void getHibernationEligibility(
in String packageName,
in AndroidFuture callback);
- void revokeOwnPermissionsOnKill(in String packageName, in List<String> permissions,
+ void revokeSelfPermissionsOnKill(in String packageName, in List<String> permissions,
in AndroidFuture callback);
}
diff --git a/core/java/android/permission/IPermissionManager.aidl b/core/java/android/permission/IPermissionManager.aidl
index 619c870..6a93b35 100644
--- a/core/java/android/permission/IPermissionManager.aidl
+++ b/core/java/android/permission/IPermissionManager.aidl
@@ -76,8 +76,6 @@
List<SplitPermissionInfoParcelable> getSplitPermissions();
- void revokeOwnPermissionsOnKill(String packageName, in List<String> permissions);
-
void startOneTimePermissionSession(String packageName, int userId, long timeout,
long revokeAfterKilledDelay, int importanceToResetTimer,
int importanceToKeepSessionAlive);
diff --git a/core/java/android/permission/PermissionControllerManager.java b/core/java/android/permission/PermissionControllerManager.java
index a005ab4e..3c2c7f0 100644
--- a/core/java/android/permission/PermissionControllerManager.java
+++ b/core/java/android/permission/PermissionControllerManager.java
@@ -916,15 +916,15 @@
* @param packageName The name of the package for which the permissions will be revoked.
* @param permissions List of permissions to be revoked.
*
- * @see Context#revokeOwnPermissionsOnKill(java.util.Collection)
+ * @see Context#revokeSelfPermissionsOnKill(java.util.Collection)
*
* @hide
*/
- public void revokeOwnPermissionsOnKill(@NonNull String packageName,
+ public void revokeSelfPermissionsOnKill(@NonNull String packageName,
@NonNull List<String> permissions) {
mRemoteService.postAsync(service -> {
AndroidFuture<Void> callback = new AndroidFuture<>();
- service.revokeOwnPermissionsOnKill(packageName, permissions, callback);
+ service.revokeSelfPermissionsOnKill(packageName, permissions, callback);
return callback;
}).whenComplete((result, err) -> {
if (err != null) {
diff --git a/core/java/android/permission/PermissionControllerService.java b/core/java/android/permission/PermissionControllerService.java
index 3292e71..4efffc5a 100644
--- a/core/java/android/permission/PermissionControllerService.java
+++ b/core/java/android/permission/PermissionControllerService.java
@@ -40,6 +40,7 @@
import android.content.Intent;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
+import android.os.Binder;
import android.os.Bundle;
import android.os.IBinder;
import android.os.ParcelFileDescriptor;
@@ -339,10 +340,10 @@
* @param permissions List of permissions to be revoked.
* @param callback Callback waiting for operation to be complete.
*
- * @see PermissionManager#revokeOwnPermissionsOnKill(java.util.Collection)
+ * @see android.content.Context#revokeSelfPermissionsOnKill(java.util.Collection)
*/
@BinderThread
- public void onRevokeOwnPermissionsOnKill(@NonNull String packageName,
+ public void onRevokeSelfPermissionsOnKill(@NonNull String packageName,
@NonNull List<String> permissions, @NonNull Runnable callback) {
throw new AbstractMethodError("Must be overridden in implementing class");
}
@@ -703,13 +704,19 @@
}
@Override
- public void revokeOwnPermissionsOnKill(@NonNull String packageName,
+ public void revokeSelfPermissionsOnKill(@NonNull String packageName,
@NonNull List<String> permissions, @NonNull AndroidFuture callback) {
try {
- enforceSomePermissionsGrantedToCaller(
- Manifest.permission.REVOKE_RUNTIME_PERMISSIONS);
Objects.requireNonNull(callback);
- onRevokeOwnPermissionsOnKill(packageName, permissions,
+
+ final int callingUid = Binder.getCallingUid();
+ int targetPackageUid = getPackageManager().getPackageUid(packageName,
+ PackageManager.PackageInfoFlags.of(0));
+ if (targetPackageUid != callingUid) {
+ enforceSomePermissionsGrantedToCaller(
+ Manifest.permission.REVOKE_RUNTIME_PERMISSIONS);
+ }
+ onRevokeSelfPermissionsOnKill(packageName, permissions,
() -> callback.complete(null));
} catch (Throwable t) {
callback.completeExceptionally(t);
diff --git a/core/java/android/permission/PermissionManager.java b/core/java/android/permission/PermissionManager.java
index c509de6..7a797ce 100644
--- a/core/java/android/permission/PermissionManager.java
+++ b/core/java/android/permission/PermissionManager.java
@@ -76,7 +76,6 @@
import com.android.internal.util.CollectionUtils;
import java.util.ArrayList;
-import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.Objects;
@@ -626,19 +625,6 @@
}
/**
- * @see Context#revokeOwnPermissionsOnKill(Collection)
- * @hide
- */
- public void revokeOwnPermissionsOnKill(@NonNull Collection<String> permissions) {
- try {
- mPermissionManager.revokeOwnPermissionsOnKill(mContext.getPackageName(),
- new ArrayList<String>(permissions));
- } catch (RemoteException e) {
- throw e.rethrowFromSystemServer();
- }
- }
-
- /**
* Gets the state flags associated with a permission.
*
* @param packageName the package name for which to get the flags
diff --git a/core/java/android/permission/PermissionUsageHelper.java b/core/java/android/permission/PermissionUsageHelper.java
index 0b57842..4ed939c 100644
--- a/core/java/android/permission/PermissionUsageHelper.java
+++ b/core/java/android/permission/PermissionUsageHelper.java
@@ -47,6 +47,7 @@
import android.content.pm.PackageManager;
import android.content.res.Resources;
import android.icu.text.ListFormatter;
+import android.location.LocationManager;
import android.media.AudioManager;
import android.os.Process;
import android.os.UserHandle;
@@ -411,10 +412,13 @@
}
/**
- * Returns true if the app supports subattribution.
+ * Returns true if the app satisfies subattribution policies and supports it
*/
private boolean isSubattributionSupported(String packageName, int uid) {
try {
+ if (!isLocationProvider(packageName)) {
+ return false;
+ }
PackageManager userPkgManager =
getUserContext(UserHandle.getUserHandleForUid(uid)).getPackageManager();
ApplicationInfo appInfo = userPkgManager.getApplicationInfoAsUser(packageName,
@@ -430,6 +434,15 @@
}
/**
+ * @param packageName
+ * @return If the package is location provider
+ */
+ private boolean isLocationProvider(String packageName) {
+ return Objects.requireNonNull(
+ mContext.getSystemService(LocationManager.class)).isProviderPackage(packageName);
+ }
+
+ /**
* Get the raw usages from the system, and then parse out the ones that are not recent enough,
* determine which permission group each belongs in, and removes duplicates (if the same app
* uses multiple permissions of the same group). Stores the package name, attribution tag, user,
diff --git a/core/java/android/provider/DeviceConfig.java b/core/java/android/provider/DeviceConfig.java
index 1008a2d..4731504 100644
--- a/core/java/android/provider/DeviceConfig.java
+++ b/core/java/android/provider/DeviceConfig.java
@@ -600,6 +600,13 @@
public static final String NAMESPACE_SELECTION_TOOLBAR = "selection_toolbar";
/**
+ * Definitions for voice interaction related functions.
+ *
+ * @hide
+ */
+ public static final String NAMESPACE_VOICE_INTERACTION = "voice_interaction";
+
+ /**
* List of namespaces which can be read without READ_DEVICE_CONFIG permission
*
* @hide
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index a6ad5e5..5191c95 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -2143,10 +2143,10 @@
/**
* Intent extra: The id of a setting restricted by supervisors.
* <p>
- * Type: Integer with a value from the SupervisorVerificationSetting annotation below.
+ * Type: Integer with a value from the one of the SUPERVISOR_VERIFICATION_* constants below.
* <ul>
- * <li>{@link #SUPERVISOR_VERIFICATION_SETTING_UNKNOWN}
- * <li>{@link #SUPERVISOR_VERIFICATION_SETTING_BIOMETRICS}
+ * <li>{@see #SUPERVISOR_VERIFICATION_SETTING_UNKNOWN}
+ * <li>{@see #SUPERVISOR_VERIFICATION_SETTING_BIOMETRICS}
* </ul>
* </p>
*/
@@ -2154,12 +2154,14 @@
"android.provider.extra.SUPERVISOR_RESTRICTED_SETTING_KEY";
/**
- * Unknown setting.
+ * The unknown setting can usually be ignored and is used for compatibility with future
+ * supervisor settings.
*/
public static final int SUPERVISOR_VERIFICATION_SETTING_UNKNOWN = 0;
/**
- * Biometric settings for supervisors.
+ * Settings for supervisors to control what kinds of biometric sensors, such a face and
+ * fingerprint scanners, can be used on the device.
*/
public static final int SUPERVISOR_VERIFICATION_SETTING_BIOMETRICS = 1;
diff --git a/core/java/android/service/ambientcontext/AmbientContextDetectionResult.java b/core/java/android/service/ambientcontext/AmbientContextDetectionResult.java
index 227194e..a216ed5 100644
--- a/core/java/android/service/ambientcontext/AmbientContextDetectionResult.java
+++ b/core/java/android/service/ambientcontext/AmbientContextDetectionResult.java
@@ -26,6 +26,7 @@
import java.util.ArrayList;
import java.util.List;
+import java.util.Objects;
/**
* Represents a {@code AmbientContextEvent} detection result reported by the detection service.
@@ -127,7 +128,9 @@
private @NonNull String mPackageName;
private long mBuilderFieldsSet = 0L;
- public Builder() {
+ public Builder(@NonNull String packageName) {
+ Objects.requireNonNull(packageName);
+ mPackageName = packageName;
}
/**
@@ -144,26 +147,37 @@
}
/**
- * The package to deliver the response to.
+ * Adds a list of events to the builder.
*/
- public @NonNull Builder setPackageName(@NonNull String value) {
+ public @NonNull Builder addEvents(@NonNull List<AmbientContextEvent> values) {
checkNotUsed();
- mBuilderFieldsSet |= 0x2;
- mPackageName = value;
+ if (mEvents == null) {
+ mBuilderFieldsSet |= 0x1;
+ mEvents = new ArrayList<>();
+ }
+ mEvents.addAll(values);
+ return this;
+ }
+
+ /**
+ * Clears all events from the builder.
+ */
+ public @NonNull Builder clearEvents() {
+ checkNotUsed();
+ if (mEvents != null) {
+ mEvents.clear();
+ }
return this;
}
/** Builds the instance. This builder should not be touched after calling this! */
public @NonNull AmbientContextDetectionResult build() {
checkNotUsed();
- mBuilderFieldsSet |= 0x4; // Mark builder used
+ mBuilderFieldsSet |= 0x2; // Mark builder used
if ((mBuilderFieldsSet & 0x1) == 0) {
mEvents = new ArrayList<>();
}
- if ((mBuilderFieldsSet & 0x2) == 0) {
- mPackageName = "";
- }
AmbientContextDetectionResult o = new AmbientContextDetectionResult(
mEvents,
mPackageName);
@@ -171,7 +185,7 @@
}
private void checkNotUsed() {
- if ((mBuilderFieldsSet & 0x4) != 0) {
+ if ((mBuilderFieldsSet & 0x2) != 0) {
throw new IllegalStateException(
"This Builder should not be reused. Use a new Builder instance instead");
}
diff --git a/core/java/android/service/ambientcontext/AmbientContextDetectionService.java b/core/java/android/service/ambientcontext/AmbientContextDetectionService.java
index 6224aa1..8cf3411 100644
--- a/core/java/android/service/ambientcontext/AmbientContextDetectionService.java
+++ b/core/java/android/service/ambientcontext/AmbientContextDetectionService.java
@@ -134,12 +134,18 @@
}
/**
- * Starts detection and provides detected events to the statusConsumer. The ongoing detection
- * will keep running, until onStopDetection is called. If there were previously requested
- * detection from the same package, the previous request will be replaced with the new request.
- * The implementation should keep track of whether the user consented each requested
- * AmbientContextEvent for the app. If not consented, the statusConsumer should get a response
- * with STATUS_ACCESS_DENIED.
+ * Called when a client app requests starting detection of the events in the request. The
+ * implementation should keep track of whether the user has explicitly consented to detecting
+ * the events using on-going ambient sensor (e.g. microphone), and agreed to share the
+ * detection results with this client app. If the user has not consented, the detection
+ * should not start, and the statusConsumer should get a response with STATUS_ACCESS_DENIED.
+ * If the user has made the consent and the underlying services are available, the
+ * implementation should start detection and provide detected events to the
+ * detectionResultConsumer. If the type of event needs immediate attention, the implementation
+ * should send result as soon as detected. Otherwise, the implementation can bulk send response.
+ * The ongoing detection will keep running, until onStopDetection is called. If there were
+ * previously requested detection from the same package, regardless of the type of events in
+ * the request, the previous request will be replaced with the new request.
*
* @param request The request with events to detect.
* @param packageName the requesting app's package name
diff --git a/core/java/android/service/ambientcontext/AmbientContextDetectionServiceStatus.java b/core/java/android/service/ambientcontext/AmbientContextDetectionServiceStatus.java
index 3e92f39..199e674 100644
--- a/core/java/android/service/ambientcontext/AmbientContextDetectionServiceStatus.java
+++ b/core/java/android/service/ambientcontext/AmbientContextDetectionServiceStatus.java
@@ -24,6 +24,8 @@
import com.android.internal.util.AnnotationValidations;
+import java.util.Objects;
+
/**
* Represents a status for the {@code AmbientContextDetectionService}.
*
@@ -121,7 +123,9 @@
private @NonNull String mPackageName;
private long mBuilderFieldsSet = 0L;
- public Builder() {
+ public Builder(@NonNull String packageName) {
+ Objects.requireNonNull(packageName);
+ mPackageName = packageName;
}
/**
@@ -134,27 +138,14 @@
return this;
}
- /**
- * The package to deliver the response to.
- */
- public @NonNull Builder setPackageName(@NonNull String value) {
- checkNotUsed();
- mBuilderFieldsSet |= 0x2;
- mPackageName = value;
- return this;
- }
-
/** Builds the instance. This builder should not be touched after calling this! */
public @NonNull AmbientContextDetectionServiceStatus build() {
checkNotUsed();
- mBuilderFieldsSet |= 0x4; // Mark builder used
+ mBuilderFieldsSet |= 0x2; // Mark builder used
if ((mBuilderFieldsSet & 0x1) == 0) {
mStatusCode = AmbientContextManager.STATUS_UNKNOWN;
}
- if ((mBuilderFieldsSet & 0x2) == 0) {
- mPackageName = "";
- }
AmbientContextDetectionServiceStatus o = new AmbientContextDetectionServiceStatus(
mStatusCode,
mPackageName);
@@ -162,7 +153,7 @@
}
private void checkNotUsed() {
- if ((mBuilderFieldsSet & 0x4) != 0) {
+ if ((mBuilderFieldsSet & 0x2) != 0) {
throw new IllegalStateException(
"This Builder should not be reused. Use a new Builder instance instead");
}
diff --git a/core/java/android/service/autofill/FillRequest.java b/core/java/android/service/autofill/FillRequest.java
index e4d3732..c73ebed 100644
--- a/core/java/android/service/autofill/FillRequest.java
+++ b/core/java/android/service/autofill/FillRequest.java
@@ -100,10 +100,10 @@
// The flag value 0x20 has been defined in AutofillManager.
/**
- * Indicates the request is coming from the activity just started.
- * @hide
+ * Indicates the request supports fill dialog presentation for the fields, the
+ * system will send the request when the activity just started.
*/
- public static final @RequestFlags int FLAG_ACTIVITY_START = 0x40;
+ public static final @RequestFlags int FLAG_SUPPORTS_FILL_DIALOG = 0x40;
/** @hide */
public static final int INVALID_REQUEST_ID = Integer.MIN_VALUE;
@@ -140,8 +140,10 @@
/**
* Gets the flags associated with this request.
*
- * @return any combination of {@link #FLAG_MANUAL_REQUEST} and
+ * @return any combination of {@link #FLAG_MANUAL_REQUEST},
+ * {@link #FLAG_SUPPORTS_FILL_DIALOG} and
* {@link #FLAG_COMPATIBILITY_MODE_REQUEST}.
+ *
*/
private final @RequestFlags int mFlags;
@@ -199,7 +201,7 @@
FLAG_COMPATIBILITY_MODE_REQUEST,
FLAG_PASSWORD_INPUT_TYPE,
FLAG_VIEW_NOT_FOCUSED,
- FLAG_ACTIVITY_START
+ FLAG_SUPPORTS_FILL_DIALOG
})
@Retention(RetentionPolicy.SOURCE)
@DataClass.Generated.Member
@@ -223,8 +225,8 @@
return "FLAG_PASSWORD_INPUT_TYPE";
case FLAG_VIEW_NOT_FOCUSED:
return "FLAG_VIEW_NOT_FOCUSED";
- case FLAG_ACTIVITY_START:
- return "FLAG_ACTIVITY_START";
+ case FLAG_SUPPORTS_FILL_DIALOG:
+ return "FLAG_SUPPORTS_FILL_DIALOG";
default: return Integer.toHexString(value);
}
}
@@ -253,7 +255,8 @@
* @param flags
* Gets the flags associated with this request.
*
- * @return any combination of {@link #FLAG_MANUAL_REQUEST} and
+ * @return any combination of {@link #FLAG_MANUAL_REQUEST},
+ * {@link #FLAG_SUPPORTS_FILL_DIALOG} and
* {@link #FLAG_COMPATIBILITY_MODE_REQUEST}.
* @param inlineSuggestionsRequest
* Gets the {@link InlineSuggestionsRequest} associated
@@ -299,7 +302,7 @@
| FLAG_COMPATIBILITY_MODE_REQUEST
| FLAG_PASSWORD_INPUT_TYPE
| FLAG_VIEW_NOT_FOCUSED
- | FLAG_ACTIVITY_START);
+ | FLAG_SUPPORTS_FILL_DIALOG);
this.mInlineSuggestionsRequest = inlineSuggestionsRequest;
this.mDelayedFillIntentSender = delayedFillIntentSender;
@@ -347,7 +350,8 @@
/**
* Gets the flags associated with this request.
*
- * @return any combination of {@link #FLAG_MANUAL_REQUEST} and
+ * @return any combination of {@link #FLAG_MANUAL_REQUEST},
+ * {@link #FLAG_SUPPORTS_FILL_DIALOG} and
* {@link #FLAG_COMPATIBILITY_MODE_REQUEST}.
*/
@DataClass.Generated.Member
@@ -458,7 +462,7 @@
| FLAG_COMPATIBILITY_MODE_REQUEST
| FLAG_PASSWORD_INPUT_TYPE
| FLAG_VIEW_NOT_FOCUSED
- | FLAG_ACTIVITY_START);
+ | FLAG_SUPPORTS_FILL_DIALOG);
this.mInlineSuggestionsRequest = inlineSuggestionsRequest;
this.mDelayedFillIntentSender = delayedFillIntentSender;
@@ -480,10 +484,10 @@
};
@DataClass.Generated(
- time = 1643386870464L,
+ time = 1647644111186L,
codegenVersion = "1.0.23",
sourceFile = "frameworks/base/core/java/android/service/autofill/FillRequest.java",
- inputSignatures = "public static final @android.service.autofill.FillRequest.RequestFlags int FLAG_MANUAL_REQUEST\npublic static final @android.service.autofill.FillRequest.RequestFlags int FLAG_COMPATIBILITY_MODE_REQUEST\npublic static final @android.service.autofill.FillRequest.RequestFlags int FLAG_PASSWORD_INPUT_TYPE\npublic static final @android.service.autofill.FillRequest.RequestFlags int FLAG_VIEW_NOT_FOCUSED\npublic static final @android.service.autofill.FillRequest.RequestFlags int FLAG_ACTIVITY_START\npublic static final int INVALID_REQUEST_ID\nprivate final int mId\nprivate final @android.annotation.NonNull java.util.List<android.service.autofill.FillContext> mFillContexts\nprivate final @android.annotation.Nullable android.os.Bundle mClientState\nprivate final @android.service.autofill.FillRequest.RequestFlags int mFlags\nprivate final @android.annotation.Nullable android.view.inputmethod.InlineSuggestionsRequest mInlineSuggestionsRequest\nprivate final @android.annotation.Nullable android.content.IntentSender mDelayedFillIntentSender\nprivate void onConstructed()\nclass FillRequest extends java.lang.Object implements [android.os.Parcelable]\n@com.android.internal.util.DataClass(genToString=true, genHiddenConstructor=true, genHiddenConstDefs=true)")
+ inputSignatures = "public static final @android.service.autofill.FillRequest.RequestFlags int FLAG_MANUAL_REQUEST\npublic static final @android.service.autofill.FillRequest.RequestFlags int FLAG_COMPATIBILITY_MODE_REQUEST\npublic static final @android.service.autofill.FillRequest.RequestFlags int FLAG_PASSWORD_INPUT_TYPE\npublic static final @android.service.autofill.FillRequest.RequestFlags int FLAG_VIEW_NOT_FOCUSED\npublic static final @android.service.autofill.FillRequest.RequestFlags int FLAG_SUPPORTS_FILL_DIALOG\npublic static final int INVALID_REQUEST_ID\nprivate final int mId\nprivate final @android.annotation.NonNull java.util.List<android.service.autofill.FillContext> mFillContexts\nprivate final @android.annotation.Nullable android.os.Bundle mClientState\nprivate final @android.service.autofill.FillRequest.RequestFlags int mFlags\nprivate final @android.annotation.Nullable android.view.inputmethod.InlineSuggestionsRequest mInlineSuggestionsRequest\nprivate final @android.annotation.Nullable android.content.IntentSender mDelayedFillIntentSender\nprivate void onConstructed()\nclass FillRequest extends java.lang.Object implements [android.os.Parcelable]\n@com.android.internal.util.DataClass(genToString=true, genHiddenConstructor=true, genHiddenConstDefs=true)")
@Deprecated
private void __metadata() {}
diff --git a/core/java/android/service/displayhash/DisplayHashingService.java b/core/java/android/service/displayhash/DisplayHashingService.java
index f22d40e..3fac23b 100644
--- a/core/java/android/service/displayhash/DisplayHashingService.java
+++ b/core/java/android/service/displayhash/DisplayHashingService.java
@@ -68,9 +68,6 @@
private DisplayHashingServiceWrapper mWrapper;
private Handler mHandler;
- public DisplayHashingService() {
- }
-
@Override
public void onCreate() {
super.onCreate();
diff --git a/core/java/android/service/games/GameSession.java b/core/java/android/service/games/GameSession.java
index 1548f52..0115294 100644
--- a/core/java/android/service/games/GameSession.java
+++ b/core/java/android/service/games/GameSession.java
@@ -426,6 +426,7 @@
* or failed.
* @throws IllegalStateException if this method is called prior to {@link #onCreate}.
*/
+ @RequiresPermission(android.Manifest.permission.MANAGE_GAME_ACTIVITY)
public void takeScreenshot(@NonNull Executor executor, @NonNull ScreenshotCallback callback) {
if (mGameSessionController == null) {
throw new IllegalStateException("Can not call before onCreate()");
diff --git a/core/java/android/service/voice/AlwaysOnHotwordDetector.java b/core/java/android/service/voice/AlwaysOnHotwordDetector.java
index bec5d1b..bc42da6 100644
--- a/core/java/android/service/voice/AlwaysOnHotwordDetector.java
+++ b/core/java/android/service/voice/AlwaysOnHotwordDetector.java
@@ -851,7 +851,8 @@
@RequiresPermission(allOf = {RECORD_AUDIO, CAPTURE_AUDIO_HOTWORD})
public void triggerHardwareRecognitionEventForTest(int status, int soundModelHandle,
boolean captureAvailable, int captureSession, int captureDelayMs, int capturePreambleMs,
- boolean triggerInData, @NonNull AudioFormat captureFormat, @Nullable byte[] data) {
+ boolean triggerInData, @NonNull AudioFormat captureFormat, @Nullable byte[] data,
+ @NonNull List<KeyphraseRecognitionExtra> keyphraseRecognitionExtras) {
Log.d(TAG, "triggerHardwareRecognitionEventForTest()");
synchronized (mLock) {
if (mAvailability == STATE_INVALID || mAvailability == STATE_ERROR) {
@@ -862,7 +863,8 @@
mModelManagementService.triggerHardwareRecognitionEventForTest(
new KeyphraseRecognitionEvent(status, soundModelHandle, captureAvailable,
captureSession, captureDelayMs, capturePreambleMs, triggerInData,
- captureFormat, data, null /* keyphraseExtras */),
+ captureFormat, data, keyphraseRecognitionExtras.toArray(
+ new KeyphraseRecognitionExtra[0])),
mInternalCallback);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
diff --git a/core/java/android/service/wallpaper/WallpaperService.java b/core/java/android/service/wallpaper/WallpaperService.java
index a2938a8..ef792d4 100644
--- a/core/java/android/service/wallpaper/WallpaperService.java
+++ b/core/java/android/service/wallpaper/WallpaperService.java
@@ -252,6 +252,7 @@
final InsetsVisibilities mRequestedVisibilities = new InsetsVisibilities();
final InsetsSourceControl[] mTempControls = new InsetsSourceControl[0];
final MergedConfiguration mMergedConfiguration = new MergedConfiguration();
+ final Bundle mSyncSeqIdBundle = new Bundle();
private final Point mSurfaceSize = new Point();
private final Point mLastSurfaceSize = new Point();
private final Matrix mTmpMatrix = new Matrix();
@@ -391,7 +392,7 @@
@Override
public void resized(ClientWindowFrames frames, boolean reportDraw,
MergedConfiguration mergedConfiguration, boolean forceLayout,
- boolean alwaysConsumeSystemBars, int displayId) {
+ boolean alwaysConsumeSystemBars, int displayId, int syncSeqId) {
Message msg = mCaller.obtainMessageIO(MSG_WINDOW_RESIZED,
reportDraw ? 1 : 0,
mergedConfiguration);
@@ -1151,7 +1152,7 @@
final int relayoutResult = mSession.relayout(
mWindow, mLayout, mWidth, mHeight,
View.VISIBLE, 0, mWinFrames, mMergedConfiguration, mSurfaceControl,
- mInsetsState, mTempControls);
+ mInsetsState, mTempControls, mSyncSeqIdBundle);
final int transformHint = SurfaceControl.rotationToBufferTransform(
(mDisplayInstallOrientation + mDisplay.getRotation()) % 4);
@@ -1338,7 +1339,8 @@
mSurfaceCreated = true;
if (redrawNeeded) {
resetWindowPages();
- mSession.finishDrawing(mWindow, null /* postDrawTransaction */);
+ mSession.finishDrawing(mWindow, null /* postDrawTransaction */,
+ Integer.MAX_VALUE);
processLocalColors(mPendingXOffset, mPendingXOffsetStep);
notifyColorsChanged();
}
diff --git a/core/java/android/text/PrecomputedText.java b/core/java/android/text/PrecomputedText.java
index 9307e56..f31a690 100644
--- a/core/java/android/text/PrecomputedText.java
+++ b/core/java/android/text/PrecomputedText.java
@@ -99,7 +99,7 @@
private final @Layout.HyphenationFrequency int mHyphenationFrequency;
// The line break configuration for calculating text wrapping.
- private final @Nullable LineBreakConfig mLineBreakConfig;
+ private final @NonNull LineBreakConfig mLineBreakConfig;
/**
* A builder for creating {@link Params}.
@@ -119,7 +119,7 @@
Layout.HYPHENATION_FREQUENCY_NORMAL;
// The line break configuration for calculating text wrapping.
- private @Nullable LineBreakConfig mLineBreakConfig;
+ private @NonNull LineBreakConfig mLineBreakConfig = LineBreakConfig.NONE;
/**
* Builder constructor.
@@ -212,7 +212,7 @@
// For the external developers, use Builder instead.
/** @hide */
public Params(@NonNull TextPaint paint,
- @Nullable LineBreakConfig lineBreakConfig,
+ @NonNull LineBreakConfig lineBreakConfig,
@NonNull TextDirectionHeuristic textDir,
@Layout.BreakStrategy int strategy,
@Layout.HyphenationFrequency int frequency) {
@@ -260,11 +260,12 @@
}
/**
- * Return the line break configuration for this text.
+ * Returns the {@link LineBreakConfig} for this text.
*
- * @return the current line break configuration, null if no line break configuration is set.
+ * @return the current line break configuration. The {@link LineBreakConfig} with default
+ * values will be returned if no line break configuration is set.
*/
- public @Nullable LineBreakConfig getLineBreakConfig() {
+ public @NonNull LineBreakConfig getLineBreakConfig() {
return mLineBreakConfig;
}
@@ -297,9 +298,9 @@
/** @hide */
public @CheckResultUsableResult int checkResultUsable(@NonNull TextPaint paint,
@NonNull TextDirectionHeuristic textDir, @Layout.BreakStrategy int strategy,
- @Layout.HyphenationFrequency int frequency, @Nullable LineBreakConfig lbConfig) {
+ @Layout.HyphenationFrequency int frequency, @NonNull LineBreakConfig lbConfig) {
if (mBreakStrategy == strategy && mHyphenationFrequency == frequency
- && isLineBreakEquals(mLineBreakConfig, lbConfig)
+ && mLineBreakConfig.equals(lbConfig)
&& mPaint.equalsForTextMeasurement(paint)) {
return mTextDir == textDir ? USABLE : NEED_RECOMPUTE;
} else {
@@ -308,29 +309,6 @@
}
/**
- * Check the two LineBreakConfig instances are equal.
- * This method assumes they are equal if one parameter is null and the other parameter has
- * a LineBreakStyle value of LineBreakConfig.LINE_BREAK_STYLE_NONE.
- *
- * @param o1 the first LineBreakConfig instance.
- * @param o2 the second LineBreakConfig instance.
- * @return true if the two LineBreakConfig instances are equal.
- */
- private boolean isLineBreakEquals(LineBreakConfig o1, LineBreakConfig o2) {
- if (Objects.equals(o1, o2)) {
- return true;
- }
- if (o1 == null && (o2 != null
- && o2.getLineBreakStyle() == LineBreakConfig.LINE_BREAK_STYLE_NONE)) {
- return true;
- } else if (o2 == null && (o1 != null
- && o1.getLineBreakStyle() == LineBreakConfig.LINE_BREAK_STYLE_NONE)) {
- return true;
- }
- return false;
- }
-
- /**
* Check if the same text layout.
*
* @return true if this and the given param result in the same text layout
diff --git a/core/java/android/text/StaticLayout.java b/core/java/android/text/StaticLayout.java
index b10fc37..2f85d2b6 100644
--- a/core/java/android/text/StaticLayout.java
+++ b/core/java/android/text/StaticLayout.java
@@ -112,6 +112,7 @@
b.mBreakStrategy = Layout.BREAK_STRATEGY_SIMPLE;
b.mHyphenationFrequency = Layout.HYPHENATION_FREQUENCY_NONE;
b.mJustificationMode = Layout.JUSTIFICATION_MODE_NONE;
+ b.mLineBreakConfig = LineBreakConfig.NONE;
return b;
}
@@ -410,7 +411,8 @@
*
* @param lineBreakConfig the line break configuration for text wrapping.
* @return this builder, useful for chaining.
- * @see android.widget.TextView#setLineBreakConfig
+ * @see android.widget.TextView#setLineBreakStyle
+ * @see android.widget.TextView#setLineBreakWordStyle
*/
@NonNull
public Builder setLineBreakConfig(@NonNull LineBreakConfig lineBreakConfig) {
@@ -454,7 +456,7 @@
@Nullable private int[] mRightIndents;
private int mJustificationMode;
private boolean mAddLastLineLineSpacing;
- private LineBreakConfig mLineBreakConfig;
+ private LineBreakConfig mLineBreakConfig = LineBreakConfig.NONE;
private final Paint.FontMetricsInt mFontMetricsInt = new Paint.FontMetricsInt();
diff --git a/core/java/android/util/FeatureFlagUtils.java b/core/java/android/util/FeatureFlagUtils.java
index 34e7ea7..fe6ae78 100644
--- a/core/java/android/util/FeatureFlagUtils.java
+++ b/core/java/android/util/FeatureFlagUtils.java
@@ -96,7 +96,7 @@
DEFAULT_FLAGS.put(SETTINGS_ENABLE_SECURITY_HUB, "true");
DEFAULT_FLAGS.put(SETTINGS_SUPPORT_LARGE_SCREEN, "true");
DEFAULT_FLAGS.put("settings_search_always_expand", "true");
- DEFAULT_FLAGS.put(SETTINGS_APP_LANGUAGE_SELECTION, "false");
+ DEFAULT_FLAGS.put(SETTINGS_APP_LANGUAGE_SELECTION, "true");
DEFAULT_FLAGS.put(SETTINGS_ENABLE_MONITOR_PHANTOM_PROCS, "true");
DEFAULT_FLAGS.put(SETTINGS_APP_ALLOW_DARK_THEME_ACTIVATION_AT_BEDTIME, "false");
DEFAULT_FLAGS.put(SETTINGS_HIDE_SECOND_LAYER_PAGE_NAVIGATE_UP_BUTTON_IN_TWO_PANE, "true");
diff --git a/core/java/android/util/IconDrawableFactory.java b/core/java/android/util/IconDrawableFactory.java
index 5bb263a..e3bc510 100644
--- a/core/java/android/util/IconDrawableFactory.java
+++ b/core/java/android/util/IconDrawableFactory.java
@@ -16,8 +16,8 @@
package android.util;
import static android.app.admin.DevicePolicyResources.Drawables.Style.SOLID_COLORED;
-import static android.app.admin.DevicePolicyResources.Drawables.UNDEFINED;
import static android.app.admin.DevicePolicyResources.Drawables.WORK_PROFILE_ICON_BADGE;
+import static android.app.admin.DevicePolicyResources.UNDEFINED;
import android.annotation.UserIdInt;
import android.app.admin.DevicePolicyManager;
@@ -88,7 +88,7 @@
}
if (mUm.hasBadge(userId)) {
- Drawable badge = mDpm.getDrawable(
+ Drawable badge = mDpm.getResources().getDrawable(
getUpdatableUserIconBadgeId(userId),
SOLID_COLORED,
() -> getDefaultUserIconBadge(userId));
diff --git a/core/java/android/util/NtpTrustedTime.java b/core/java/android/util/NtpTrustedTime.java
index aebc5e8..01a037a 100644
--- a/core/java/android/util/NtpTrustedTime.java
+++ b/core/java/android/util/NtpTrustedTime.java
@@ -140,6 +140,10 @@
/** An in-memory config override for use during tests. */
@Nullable
+ private Integer mPortForTests;
+
+ /** An in-memory config override for use during tests. */
+ @Nullable
private Duration mTimeoutForTests;
// Declared volatile and accessed outside of synchronized blocks to avoid blocking reads during
@@ -163,9 +167,11 @@
* Overrides the NTP server config for tests. Passing {@code null} to a parameter clears the
* test value, i.e. so the normal value will be used next time.
*/
- public void setServerConfigForTests(@Nullable String hostname, @Nullable Duration timeout) {
+ public void setServerConfigForTests(
+ @Nullable String hostname, @Nullable Integer port, @Nullable Duration timeout) {
synchronized (this) {
mHostnameForTests = hostname;
+ mPortForTests = port;
mTimeoutForTests = timeout;
}
}
@@ -195,8 +201,9 @@
if (LOGD) Log.d(TAG, "forceRefresh() from cache miss");
final SntpClient client = new SntpClient();
final String serverName = connectionInfo.getServer();
+ final int port = connectionInfo.getPort();
final int timeoutMillis = connectionInfo.getTimeoutMillis();
- if (client.requestTime(serverName, timeoutMillis, network)) {
+ if (client.requestTime(serverName, port, timeoutMillis, network)) {
long ntpCertainty = client.getRoundTripTime() / 2;
mTimeResult = new TimeResult(
client.getNtpTime(), client.getNtpTimeReference(), ntpCertainty);
@@ -297,10 +304,12 @@
private static class NtpConnectionInfo {
@NonNull private final String mServer;
+ private final int mPort;
private final int mTimeoutMillis;
- NtpConnectionInfo(@NonNull String server, int timeoutMillis) {
+ NtpConnectionInfo(@NonNull String server, int port, int timeoutMillis) {
mServer = Objects.requireNonNull(server);
+ mPort = port;
mTimeoutMillis = timeoutMillis;
}
@@ -309,6 +318,11 @@
return mServer;
}
+ @NonNull
+ public int getPort() {
+ return mPort;
+ }
+
int getTimeoutMillis() {
return mTimeoutMillis;
}
@@ -317,6 +331,7 @@
public String toString() {
return "NtpConnectionInfo{"
+ "mServer='" + mServer + '\''
+ + ", mPort='" + mPort + '\''
+ ", mTimeoutMillis=" + mTimeoutMillis
+ '}';
}
@@ -341,6 +356,13 @@
}
}
+ final Integer port;
+ if (mPortForTests != null) {
+ port = mPortForTests;
+ } else {
+ port = SntpClient.STANDARD_NTP_PORT;
+ }
+
final int timeoutMillis;
if (mTimeoutForTests != null) {
timeoutMillis = (int) mTimeoutForTests.toMillis();
@@ -350,7 +372,8 @@
timeoutMillis = Settings.Global.getInt(
resolver, Settings.Global.NTP_TIMEOUT, defaultTimeoutMillis);
}
- return TextUtils.isEmpty(hostname) ? null : new NtpConnectionInfo(hostname, timeoutMillis);
+ return TextUtils.isEmpty(hostname) ? null :
+ new NtpConnectionInfo(hostname, port, timeoutMillis);
}
/** Prints debug information. */
diff --git a/core/java/android/util/TimingsTraceLog.java b/core/java/android/util/TimingsTraceLog.java
index 066709f..48a5cea 100644
--- a/core/java/android/util/TimingsTraceLog.java
+++ b/core/java/android/util/TimingsTraceLog.java
@@ -147,7 +147,7 @@
* Logs a duration so it can be parsed by external tools for performance reporting.
*/
public void logDuration(String name, long timeMs) {
- Slog.d(mTag, name + " took to complete: " + timeMs + "ms");
+ Slog.v(mTag, name + " took to complete: " + timeMs + "ms");
}
/**
diff --git a/core/java/android/view/ContentRecordingSession.java b/core/java/android/view/ContentRecordingSession.java
index db4ec11..c66c70af 100644
--- a/core/java/android/view/ContentRecordingSession.java
+++ b/core/java/android/view/ContentRecordingSession.java
@@ -66,10 +66,11 @@
private int mContentToRecord = RECORD_CONTENT_DISPLAY;
/**
- * The window token of the layer of the hierarchy to record.
- * The display content if {@link #getContentToRecord()} is
- * {@link RecordContent#RECORD_CONTENT_DISPLAY}, or task if {@link #getContentToRecord()} is
- * {@link RecordContent#RECORD_CONTENT_TASK}.
+ * The token of the layer of the hierarchy to record.
+ * If {@link #getContentToRecord()} is @link RecordContent#RECORD_CONTENT_DISPLAY}, then
+ * represents the WindowToken corresponding to the DisplayContent to record.
+ * If {@link #getContentToRecord()} is {@link RecordContent#RECORD_CONTENT_TASK}, then
+ * represents the {@link android.window.WindowContainerToken} of the Task to record.
*/
@VisibleForTesting
@Nullable
@@ -192,10 +193,11 @@
}
/**
- * The window token of the layer of the hierarchy to record.
- * The display content if {@link #getContentToRecord()} is
- * {@link RecordContent#RECORD_CONTENT_DISPLAY}, or task if {@link #getContentToRecord()} is
- * {@link RecordContent#RECORD_CONTENT_TASK}.
+ * {The token of the layer of the hierarchy to record.
+ * If {@link #getContentToRecord()} is @link RecordContent#RECORD_CONTENT_DISPLAY}, then
+ * represents the WindowToken corresponding to the DisplayContent to record.
+ * If {@link #getContentToRecord()} is {@link RecordContent#RECORD_CONTENT_TASK}, then
+ * represents the {@link android.window.WindowContainerToken} of the Task to record.
*/
@DataClass.Generated.Member
public @VisibleForTesting @Nullable IBinder getTokenToRecord() {
@@ -231,10 +233,11 @@
}
/**
- * The window token of the layer of the hierarchy to record.
- * The display content if {@link #getContentToRecord()} is
- * {@link RecordContent#RECORD_CONTENT_DISPLAY}, or task if {@link #getContentToRecord()} is
- * {@link RecordContent#RECORD_CONTENT_TASK}.
+ * {The token of the layer of the hierarchy to record.
+ * If {@link #getContentToRecord()} is @link RecordContent#RECORD_CONTENT_DISPLAY}, then
+ * represents the WindowToken corresponding to the DisplayContent to record.
+ * If {@link #getContentToRecord()} is {@link RecordContent#RECORD_CONTENT_TASK}, then
+ * represents the {@link android.window.WindowContainerToken} of the Task to record.
*/
@DataClass.Generated.Member
public @NonNull ContentRecordingSession setTokenToRecord(@VisibleForTesting @NonNull IBinder value) {
@@ -390,10 +393,11 @@
}
/**
- * The window token of the layer of the hierarchy to record.
- * The display content if {@link #getContentToRecord()} is
- * {@link RecordContent#RECORD_CONTENT_DISPLAY}, or task if {@link #getContentToRecord()} is
- * {@link RecordContent#RECORD_CONTENT_TASK}.
+ * {The token of the layer of the hierarchy to record.
+ * If {@link #getContentToRecord()} is @link RecordContent#RECORD_CONTENT_DISPLAY}, then
+ * represents the WindowToken corresponding to the DisplayContent to record.
+ * If {@link #getContentToRecord()} is {@link RecordContent#RECORD_CONTENT_TASK}, then
+ * represents the {@link android.window.WindowContainerToken} of the Task to record.
*/
@DataClass.Generated.Member
public @NonNull Builder setTokenToRecord(@VisibleForTesting @NonNull IBinder value) {
@@ -433,7 +437,7 @@
}
@DataClass.Generated(
- time = 1644843382972L,
+ time = 1645803878639L,
codegenVersion = "1.0.23",
sourceFile = "frameworks/base/core/java/android/view/ContentRecordingSession.java",
inputSignatures = "public static final int RECORD_CONTENT_DISPLAY\npublic static final int RECORD_CONTENT_TASK\nprivate int mDisplayId\nprivate @android.view.ContentRecordingSession.RecordContent int mContentToRecord\nprivate @com.android.internal.annotations.VisibleForTesting @android.annotation.Nullable android.os.IBinder mTokenToRecord\npublic static android.view.ContentRecordingSession createDisplaySession(android.os.IBinder)\npublic static android.view.ContentRecordingSession createTaskSession(android.os.IBinder)\npublic static boolean isValid(android.view.ContentRecordingSession)\npublic static boolean isSameDisplay(android.view.ContentRecordingSession,android.view.ContentRecordingSession)\nclass ContentRecordingSession extends java.lang.Object implements [android.os.Parcelable]\n@com.android.internal.util.DataClass(genConstructor=false, genToString=true, genSetters=true, genEqualsHashCode=true)")
diff --git a/core/java/android/view/HandwritingInitiator.java b/core/java/android/view/HandwritingInitiator.java
index c1413be..61098d6 100644
--- a/core/java/android/view/HandwritingInitiator.java
+++ b/core/java/android/view/HandwritingInitiator.java
@@ -55,10 +55,10 @@
*/
private final int mTouchSlop;
/**
- * The timeout used to distinguish tap from handwriting. If the stylus doesn't move before this
- * timeout, it's not considered as handwriting.
+ * The timeout used to distinguish tap or long click from handwriting. If the stylus doesn't
+ * move before this timeout, it's not considered as handwriting.
*/
- private final long mTapTimeoutInMillis;
+ private final long mHandwritingTimeoutInMillis;
private State mState = new State();
private final HandwritingAreaTracker mHandwritingAreasTracker = new HandwritingAreaTracker();
@@ -90,7 +90,7 @@
public HandwritingInitiator(@NonNull ViewConfiguration viewConfiguration,
@NonNull InputMethodManager inputMethodManager) {
mTouchSlop = viewConfiguration.getScaledTouchSlop();
- mTapTimeoutInMillis = ViewConfiguration.getTapTimeout();
+ mHandwritingTimeoutInMillis = ViewConfiguration.getLongPressTimeout();
mImm = inputMethodManager;
}
@@ -145,7 +145,7 @@
final long timeElapsed =
motionEvent.getEventTime() - mState.mStylusDownTimeInMillis;
- if (timeElapsed > mTapTimeoutInMillis) {
+ if (timeElapsed > mHandwritingTimeoutInMillis) {
reset();
return;
}
@@ -249,19 +249,19 @@
return;
}
- Rect handwritingArea = getViewHandwritingArea(connectedView);
- if (handwritingArea != null) {
- if (contains(handwritingArea, mState.mStylusDownX, mState.mStylusDownY)) {
- startHandwriting(connectedView);
- }
+ final Rect handwritingArea = getViewHandwritingArea(connectedView);
+ if (contains(handwritingArea, mState.mStylusDownX, mState.mStylusDownY)) {
+ startHandwriting(connectedView);
+ } else {
+ reset();
}
- reset();
}
/** For test only. */
@VisibleForTesting
public void startHandwriting(@NonNull View view) {
mImm.startStylusHandwriting(view);
+ reset();
}
/**
@@ -287,7 +287,7 @@
final View connectedView = getConnectedView();
if (connectedView != null && connectedView.isAutoHandwritingEnabled()) {
final Rect handwritingArea = getViewHandwritingArea(connectedView);
- if (handwritingArea != null && contains(handwritingArea, x, y)) {
+ if (contains(handwritingArea, x, y)) {
return connectedView;
}
}
@@ -298,8 +298,7 @@
for (HandwritableViewInfo viewInfo : handwritableViewInfos) {
final View view = viewInfo.getView();
if (!view.isAutoHandwritingEnabled()) continue;
- final Rect rect = viewInfo.getHandwritingArea();
- if (rect != null && contains(rect, x, y)) {
+ if (contains(viewInfo.getHandwritingArea(), x, y)) {
return viewInfo.getView();
}
}
@@ -315,12 +314,15 @@
private static Rect getViewHandwritingArea(@NonNull View view) {
final ViewParent viewParent = view.getParent();
if (viewParent != null && view.isAttachedToWindow() && view.isAggregatedVisible()) {
- Rect handwritingArea = view.getHandwritingArea();
- if (handwritingArea == null) {
- handwritingArea = new Rect(0, 0, view.getWidth(), view.getHeight());
+ final Rect localHandwritingArea = view.getHandwritingArea();
+ final Rect globalHandwritingArea = new Rect();
+ if (localHandwritingArea != null) {
+ globalHandwritingArea.set(localHandwritingArea);
+ } else {
+ globalHandwritingArea.set(0, 0, view.getWidth(), view.getHeight());
}
- if (viewParent.getChildVisibleRect(view, handwritingArea, null)) {
- return handwritingArea;
+ if (viewParent.getChildVisibleRect(view, globalHandwritingArea, null)) {
+ return globalHandwritingArea;
}
}
return null;
@@ -329,7 +331,8 @@
/**
* Return true if the (x, y) is inside by the given {@link Rect}.
*/
- private boolean contains(@NonNull Rect rect, float x, float y) {
+ private boolean contains(@Nullable Rect rect, float x, float y) {
+ if (rect == null) return false;
return x >= rect.left && x < rect.right && y >= rect.top && y < rect.bottom;
}
@@ -481,17 +484,18 @@
if (!mIsDirty) {
return true;
}
- final Rect localRect = view.getHandwritingArea();
- if (localRect == null) {
+ final Rect handwritingArea = view.getHandwritingArea();
+ if (handwritingArea == null) {
return false;
}
ViewParent parent = view.getParent();
if (parent != null) {
- final Rect newRect = new Rect(localRect);
- if (parent.getChildVisibleRect(view, newRect, null /* offset */)) {
- mHandwritingArea = newRect;
- } else {
+ if (mHandwritingArea == null) {
+ mHandwritingArea = new Rect();
+ }
+ mHandwritingArea.set(handwritingArea);
+ if (!parent.getChildVisibleRect(view, mHandwritingArea, null /* offset */)) {
mHandwritingArea = null;
}
}
diff --git a/core/java/android/view/IWindow.aidl b/core/java/android/view/IWindow.aidl
index 12421ed..1f6cee6 100644
--- a/core/java/android/view/IWindow.aidl
+++ b/core/java/android/view/IWindow.aidl
@@ -55,7 +55,8 @@
void resized(in ClientWindowFrames frames, boolean reportDraw,
in MergedConfiguration newMergedConfiguration,
- boolean forceLayout, boolean alwaysConsumeSystemBars, int displayId);
+ boolean forceLayout, boolean alwaysConsumeSystemBars, int displayId,
+ int syncSeqId);
/**
* Called when the window insets configuration has changed.
diff --git a/core/java/android/view/IWindowSession.aidl b/core/java/android/view/IWindowSession.aidl
index 5c7c844..fd86900 100644
--- a/core/java/android/view/IWindowSession.aidl
+++ b/core/java/android/view/IWindowSession.aidl
@@ -104,7 +104,8 @@
int requestedWidth, int requestedHeight, int viewVisibility,
int flags, out ClientWindowFrames outFrames,
out MergedConfiguration outMergedConfiguration, out SurfaceControl outSurfaceControl,
- out InsetsState insetsState, out InsetsSourceControl[] activeControls);
+ out InsetsState insetsState, out InsetsSourceControl[] activeControls,
+ out Bundle bundle);
/*
* Notify the window manager that an application is relaunching and
@@ -142,7 +143,8 @@
* is null if there is no sync required.
*/
@UnsupportedAppUsage
- oneway void finishDrawing(IWindow window, in SurfaceControl.Transaction postDrawTransaction);
+ oneway void finishDrawing(IWindow window, in SurfaceControl.Transaction postDrawTransaction,
+ int seqId);
@UnsupportedAppUsage
oneway void setInTouchMode(boolean showFocus);
diff --git a/core/java/android/view/SurfaceControl.java b/core/java/android/view/SurfaceControl.java
index 64f5668..da582c5 100644
--- a/core/java/android/view/SurfaceControl.java
+++ b/core/java/android/view/SurfaceControl.java
@@ -64,6 +64,7 @@
import android.view.Surface.OutOfResourcesException;
import com.android.internal.annotations.GuardedBy;
+import com.android.internal.util.Preconditions;
import com.android.internal.util.VirtualRefBasePtr;
import dalvik.system.CloseGuard;
@@ -82,6 +83,7 @@
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.Executor;
import java.util.concurrent.TimeUnit;
+import java.util.function.Consumer;
/**
* Handle to an on-screen Surface managed by the system compositor. The SurfaceControl is
@@ -212,7 +214,7 @@
private static native void nativeReparent(long transactionObj, long nativeObject,
long newParentNativeObject);
private static native void nativeSetBuffer(long transactionObj, long nativeObject,
- HardwareBuffer buffer, long fencePtr);
+ HardwareBuffer buffer, long fencePtr, Consumer<SyncFence> releaseCallback);
private static native void nativeSetBufferTransform(long transactionObj, long nativeObject,
int transform);
private static native void nativeSetDataSpace(long transactionObj, long nativeObject,
@@ -2961,6 +2963,8 @@
@NonNull
public Transaction setScale(@NonNull SurfaceControl sc, float scaleX, float scaleY) {
checkPreconditions(sc);
+ Preconditions.checkArgument(scaleX >= 0, "Negative value passed in for scaleX");
+ Preconditions.checkArgument(scaleY >= 0, "Negative value passed in for scaleY");
nativeSetScale(mNativeObject, sc.mNativeObject, scaleX, scaleY);
return this;
}
@@ -3205,6 +3209,7 @@
public @NonNull Transaction setCrop(@NonNull SurfaceControl sc, @Nullable Rect crop) {
checkPreconditions(sc);
if (crop != null) {
+ Preconditions.checkArgument(crop.isValid(), "Crop isn't valid.");
nativeSetWindowCrop(mNativeObject, sc.mNativeObject,
crop.left, crop.top, crop.right, crop.bottom);
} else {
@@ -3740,18 +3745,62 @@
*/
public @NonNull Transaction setBuffer(@NonNull SurfaceControl sc,
@Nullable HardwareBuffer buffer, @Nullable SyncFence fence) {
+ return setBuffer(sc, buffer, fence, null);
+ }
+
+ /**
+ * Updates the HardwareBuffer displayed for the SurfaceControl.
+ *
+ * Note that the buffer must be allocated with {@link HardwareBuffer#USAGE_COMPOSER_OVERLAY}
+ * as well as {@link HardwareBuffer#USAGE_GPU_SAMPLED_IMAGE} as the surface control might
+ * be composited using either an overlay or using the GPU.
+ *
+ * A presentation fence may be passed to improve performance by allowing the buffer
+ * to complete rendering while it is waiting for the transaction to be applied.
+ * For example, if the buffer is being produced by rendering with OpenGL ES then
+ * a fence created with
+ * {@link android.opengl.EGLExt#eglDupNativeFenceFDANDROID(EGLDisplay, EGLSync)} can be
+ * used to allow the GPU rendering to be concurrent with the transaction. The compositor
+ * will wait for the fence to be signaled before the buffer is displayed. If multiple
+ * buffers are set as part of the same transaction, the presentation fences of all of them
+ * must signal before any buffer is displayed. That is, the entire transaction is delayed
+ * until all presentation fences have signaled, ensuring the transaction remains consistent.
+ *
+ * A releaseCallback may be passed to know when the buffer is safe to be reused. This
+ * is recommended when attempting to render continuously using SurfaceControl transactions
+ * instead of through {@link Surface}, as it provides a safe & reliable way to know when
+ * a buffer can be re-used. The callback will be invoked with a {@link SyncFence} which,
+ * if {@link SyncFence#isValid() valid}, must be waited on prior to using the buffer. This
+ * can either be done directly with {@link SyncFence#awaitForever()} or it may be done
+ * indirectly such as passing it as a release fence to
+ * {@link android.media.Image#setFence(SyncFence)} when using
+ * {@link android.media.ImageReader}.
+ *
+ * @param sc The SurfaceControl to update
+ * @param buffer The buffer to be displayed
+ * @param fence The presentation fence. If null or invalid, this is equivalent to
+ * {@link #setBuffer(SurfaceControl, HardwareBuffer)}
+ * @param releaseCallback The callback to invoke when the buffer being set has been released
+ * by a later transaction. That is, the point at which it is safe
+ * to re-use the buffer.
+ * @return this
+ */
+ public @NonNull Transaction setBuffer(@NonNull SurfaceControl sc,
+ @Nullable HardwareBuffer buffer, @Nullable SyncFence fence,
+ @Nullable Consumer<SyncFence> releaseCallback) {
checkPreconditions(sc);
if (fence != null) {
synchronized (fence.getLock()) {
nativeSetBuffer(mNativeObject, sc.mNativeObject, buffer,
- fence.getNativeFence());
+ fence.getNativeFence(), releaseCallback);
}
} else {
- nativeSetBuffer(mNativeObject, sc.mNativeObject, buffer, 0);
+ nativeSetBuffer(mNativeObject, sc.mNativeObject, buffer, 0, releaseCallback);
}
return this;
}
+
/**
* Sets the buffer transform that should be applied to the current buffer.
*
@@ -4090,4 +4139,10 @@
return -1;
}
+
+ // Called by native
+ private static void invokeReleaseCallback(Consumer<SyncFence> callback, long nativeFencePtr) {
+ SyncFence fence = new SyncFence(nativeFencePtr);
+ callback.accept(fence);
+ }
}
diff --git a/core/java/android/view/SurfaceControlViewHost.java b/core/java/android/view/SurfaceControlViewHost.java
index a13579d..406281d 100644
--- a/core/java/android/view/SurfaceControlViewHost.java
+++ b/core/java/android/view/SurfaceControlViewHost.java
@@ -401,7 +401,7 @@
public void relayout(WindowManager.LayoutParams attrs,
WindowlessWindowManager.ResizeCompleteCallback callback) {
mViewRoot.setLayoutParams(attrs, false);
- mViewRoot.setReportNextDraw();
+ mViewRoot.setReportNextDraw(true /* syncBuffer */);
mWm.setCompletionCallback(mViewRoot.mWindow.asBinder(), callback);
}
diff --git a/core/java/android/view/SurfaceView.java b/core/java/android/view/SurfaceView.java
index 4138556..22ccaae 100644
--- a/core/java/android/view/SurfaceView.java
+++ b/core/java/android/view/SurfaceView.java
@@ -50,6 +50,7 @@
import com.android.internal.view.SurfaceCallbackHelper;
import java.util.ArrayList;
+import java.util.concurrent.CountDownLatch;
import java.util.concurrent.locks.ReentrantLock;
import java.util.function.Consumer;
@@ -203,8 +204,6 @@
private int mSurfaceFlags = SurfaceControl.HIDDEN;
- private int mPendingReportDraws;
-
/**
* Transaction that should be used from the render thread. This transaction is only thread safe
* with other calls directly from the render thread.
@@ -212,11 +211,6 @@
private final SurfaceControl.Transaction mRtTransaction = new SurfaceControl.Transaction();
/**
- * Used on the main thread to set the transaction that will be synced with the main window.
- */
- private final Transaction mSyncTransaction = new Transaction();
-
- /**
* Transaction that should be used whe
* {@link HardwareRenderer.FrameDrawingCallback#onFrameDraw} is invoked. All
* frame callbacks can use the same transaction since they will be thread safe
@@ -391,31 +385,12 @@
}
}
- private void performDrawFinished(@Nullable Transaction t) {
- if (t != null) {
- mSyncTransaction.merge(t);
+ private void performDrawFinished() {
+ mDrawFinished = true;
+ if (mAttachedToWindow) {
+ mParent.requestTransparentRegion(SurfaceView.this);
+ invalidate();
}
-
- if (mPendingReportDraws > 0) {
- mDrawFinished = true;
- if (mAttachedToWindow) {
- mParent.requestTransparentRegion(SurfaceView.this);
- notifyDrawFinished();
- invalidate();
- }
- } else {
- Log.e(TAG, System.identityHashCode(this) + "finished drawing"
- + " but no pending report draw (extra call"
- + " to draw completion runnable?)");
- }
- }
-
- void notifyDrawFinished() {
- ViewRootImpl viewRoot = getViewRootImpl();
- if (viewRoot != null) {
- viewRoot.pendingDrawFinished(mSyncTransaction);
- }
- mPendingReportDraws--;
}
@Override
@@ -438,10 +413,6 @@
mGlobalListenersAdded = false;
}
- while (mPendingReportDraws > 0) {
- notifyDrawFinished();
- }
-
mRequestedVisible = false;
updateSurface();
@@ -993,10 +964,17 @@
return;
}
- final boolean realSizeChanged = performSurfaceTransaction(viewRoot,
- translator, creating, sizeChanged, hintChanged, surfaceUpdateTransaction);
final boolean redrawNeeded = sizeChanged || creating || hintChanged
|| (mVisible && !mDrawFinished);
+ final TransactionCallback transactionCallback =
+ redrawNeeded ? new TransactionCallback() : null;
+ if (redrawNeeded && viewRoot.wasRelayoutRequested()) {
+ mBlastBufferQueue.syncNextTransaction(
+ false /* acquireSingleBuffer */,
+ transactionCallback::onTransactionReady);
+ }
+ final boolean realSizeChanged = performSurfaceTransaction(viewRoot,
+ translator, creating, sizeChanged, hintChanged, surfaceUpdateTransaction);
try {
SurfaceHolder.Callback[] callbacks = null;
@@ -1015,9 +993,7 @@
mIsCreating = true;
if (DEBUG) Log.i(TAG, System.identityHashCode(this) + " "
+ "visibleChanged -- surfaceCreated");
- if (callbacks == null) {
- callbacks = getSurfaceCallbacks();
- }
+ callbacks = getSurfaceCallbacks();
for (SurfaceHolder.Callback c : callbacks) {
c.surfaceCreated(mSurfaceHolder);
}
@@ -1035,32 +1011,7 @@
}
}
if (redrawNeeded) {
- if (DEBUG) Log.i(TAG, System.identityHashCode(this) + " "
- + "surfaceRedrawNeeded");
- if (callbacks == null) {
- callbacks = getSurfaceCallbacks();
- }
-
- final boolean wasRelayoutRequested = viewRoot.wasRelayoutRequested();
- if (wasRelayoutRequested && (mBlastBufferQueue != null)) {
- mBlastBufferQueue.syncNextTransaction(
- false /* acquireSingleBuffer */,
- this::onDrawFinished);
- }
- mPendingReportDraws++;
- viewRoot.drawPending();
- SurfaceCallbackHelper sch = new SurfaceCallbackHelper(() -> {
- if (mBlastBufferQueue != null) {
- mBlastBufferQueue.stopContinuousSyncTransaction();
- }
- // If relayout was requested, then a callback from BBQ will
- // be invoked with the sync transaction. onDrawFinished will be
- // called in there
- if (!wasRelayoutRequested) {
- onDrawFinished(null);
- }
- });
- sch.dispatchSurfaceRedrawNeededAsync(mSurfaceHolder, callbacks);
+ redrawNeeded(callbacks, transactionCallback);
}
}
} finally {
@@ -1079,6 +1030,64 @@
}
}
+ private void redrawNeeded(SurfaceHolder.Callback[] callbacks,
+ @Nullable TransactionCallback transactionCallback) {
+ if (DEBUG) {
+ Log.i(TAG, System.identityHashCode(this) + " surfaceRedrawNeeded");
+ }
+ final SurfaceHolder.Callback[] capturedCallbacks =
+ callbacks == null ? getSurfaceCallbacks() : callbacks;
+
+ ViewRootImpl viewRoot = getViewRootImpl();
+ boolean isVriSync = viewRoot.addToSync(syncBufferCallback ->
+ redrawNeededAsync(capturedCallbacks, () -> {
+ if (mBlastBufferQueue != null) {
+ mBlastBufferQueue.stopContinuousSyncTransaction();
+ }
+
+ Transaction t = null;
+ if (transactionCallback != null && mBlastBufferQueue != null) {
+ t = transactionCallback.waitForTransaction();
+ }
+ // If relayout was requested, then a callback from BBQ will
+ // be invoked with the sync transaction. onDrawFinished will be
+ // called in there
+ syncBufferCallback.onBufferReady(t);
+ onDrawFinished();
+ }));
+
+ // If isVriSync, then everything was setup in the addToSync.
+ if (isVriSync) {
+ return;
+ }
+
+ redrawNeededAsync(capturedCallbacks, this::onDrawFinished);
+ }
+
+ private void redrawNeededAsync(SurfaceHolder.Callback[] callbacks,
+ Runnable callbacksCollected) {
+ SurfaceCallbackHelper sch = new SurfaceCallbackHelper(callbacksCollected);
+ sch.dispatchSurfaceRedrawNeededAsync(mSurfaceHolder, callbacks);
+ }
+
+ private static class TransactionCallback {
+ private final CountDownLatch mCountDownLatch = new CountDownLatch(1);
+ private Transaction mTransaction;
+
+ Transaction waitForTransaction() {
+ try {
+ mCountDownLatch.await();
+ } catch (InterruptedException e) {
+ }
+ return mTransaction;
+ }
+
+ void onTransactionReady(Transaction t) {
+ mTransaction = t;
+ mCountDownLatch.countDown();
+ }
+ }
+
/**
* Copy the Surface from the SurfaceControl or the blast adapter.
*
@@ -1189,13 +1198,13 @@
mBlastBufferQueue.update(mBlastSurfaceControl, mSurfaceWidth, mSurfaceHeight, mFormat);
}
- private void onDrawFinished(@Nullable Transaction t) {
+ private void onDrawFinished() {
if (DEBUG) {
Log.i(TAG, System.identityHashCode(this) + " "
+ "finishedDrawing");
}
- runOnUiThread(() -> performDrawFinished(t));
+ runOnUiThread(this::performDrawFinished);
}
/**
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index c222991..1b8dc70 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -12016,7 +12016,6 @@
/**
* Return the handwriting areas set on this view, in its local coordinates.
- * Notice: the caller of this method should not modify the Rect returned.
* @see #setHandwritingArea(Rect)
*
* @hide
@@ -12025,7 +12024,7 @@
public Rect getHandwritingArea() {
final ListenerInfo info = mListenerInfo;
if (info != null) {
- return info.mHandwritingArea;
+ return new Rect(info.mHandwritingArea);
}
return null;
}
@@ -15617,7 +15616,7 @@
* @param event the KeyEvent object that defines the button action
*/
public boolean onKeyDown(int keyCode, KeyEvent event) {
- if (event.hasNoModifiers() && KeyEvent.isConfirmKey(keyCode)) {
+ if (KeyEvent.isConfirmKey(keyCode) && event.hasNoModifiers()) {
if ((mViewFlags & ENABLED_MASK) == DISABLED) {
return true;
}
@@ -15674,7 +15673,7 @@
* @param event The KeyEvent object that defines the button action.
*/
public boolean onKeyUp(int keyCode, KeyEvent event) {
- if (event.hasNoModifiers() && KeyEvent.isConfirmKey(keyCode)) {
+ if (KeyEvent.isConfirmKey(keyCode) && event.hasNoModifiers()) {
if ((mViewFlags & ENABLED_MASK) == DISABLED) {
return true;
}
diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java
index e79bdce..b90f54b 100644
--- a/core/java/android/view/ViewRootImpl.java
+++ b/core/java/android/view/ViewRootImpl.java
@@ -552,7 +552,6 @@
private final Rect mVisRect = new Rect(); // used to retrieve visible rect of focused view.
private final Rect mTempRect = new Rect();
- private final Rect mTempRect2 = new Rect();
private final WindowLayout mWindowLayout = new WindowLayout();
@@ -584,11 +583,15 @@
boolean mReportNextDraw;
+
/**
- * Set whether the draw should use blast sync. This is in case the draw is canceled,
- * but will be rescheduled. We still want the next draw to be sync.
+ * Set whether the draw should send the buffer to system server. When set to true, VRI will
+ * create a sync transaction with BBQ and send the resulting buffer to system server. If false,
+ * VRI will not try to sync a buffer in BBQ, but still report when a draw occurred.
+ *
+ * Default is true since we normally want to sync the buffer.
*/
- boolean mNextDrawUseBlastSync;
+ private boolean mSyncBuffer = true;
boolean mFullRedrawNeeded;
boolean mNewSurfaceNeeded;
@@ -809,6 +812,10 @@
return mHandwritingInitiator;
}
+ private final SurfaceSyncer mSurfaceSyncer = new SurfaceSyncer();
+ private int mLastSyncId = -1;
+ private SurfaceSyncer.SyncBufferCallback mSyncBufferCallback;
+
/**
* Keeps track of the last frame number that was attempted to draw. Should only be accessed on
* the RenderThread.
@@ -830,6 +837,25 @@
private int mLastTransformHint = Integer.MIN_VALUE;
+ /**
+ * A temporary object used so relayoutWindow can return the latest SyncSeqId
+ * system. The SyncSeqId system was designed to work without synchronous relayout
+ * window, and actually synchronous relayout window presents a problem. We could have
+ * a sequence like this:
+ * 1. We send MSG_RESIZED to the client with a new syncSeqId to begin a new sync
+ * 2. Due to scheduling the client executes performTraversals before calling MSG_RESIZED
+ * 3. Coincidentally for some random reason it also calls relayout
+ * 4. It observes the new state from relayout, and so the next frame will contain the state
+ * However it hasn't received the seqId yet, and so under the designed operation of
+ * seqId flowing through MSG_RESIZED, the next frame wouldn't be synced. Since it
+ * contains our target sync state, we need to sync it! This problem won't come up once
+ * we get rid of synchronous relayout, until then, we use this bundle to channel the
+ * integer back over relayout.
+ */
+ private Bundle mRelayoutBundle = new Bundle();
+ private int mSyncSeqId = 0;
+ private int mLastSyncSeqId = 0;
+
private String mTag = TAG;
public ViewRootImpl(Context context, Display display) {
@@ -1205,8 +1231,7 @@
displayCutoutSafe, winConfig.getBounds(), winConfig.getWindowingMode(),
UNSPECIFIED_LENGTH, UNSPECIFIED_LENGTH,
mInsetsController.getRequestedVisibilities(),
- getAttachedWindowFrame(), 1f /* compactScale */,
- mTmpFrames.displayFrame, mTempRect2, mTmpFrames.frame);
+ getAttachedWindowFrame(), 1f /* compactScale */, mTmpFrames);
setFrame(mTmpFrames.frame);
registerBackCallbackOnWindow();
if (!WindowOnBackInvokedDispatcher.isOnBackInvokedCallbackEnabled(mContext)) {
@@ -1711,6 +1736,7 @@
mPendingBackDropFrame.set(backdropFrame);
mForceNextWindowRelayout = forceNextWindowRelayout;
mPendingAlwaysConsumeSystemBars = args.argi2 != 0;
+ mSyncSeqId = args.argi4;
if (msg == MSG_RESIZED_REPORT) {
reportNextDraw();
@@ -2863,8 +2889,6 @@
mView.onSystemBarAppearanceChanged(mDispatchedSystemBarAppearance);
}
}
- final boolean wasReportNextDraw = mReportNextDraw;
- boolean useBlastSync = mNextDrawUseBlastSync;
if (mFirst || windowShouldResize || viewVisibilityChanged || params != null
|| mForceNextWindowRelayout) {
@@ -2901,14 +2925,12 @@
final boolean dockedResizing = (relayoutResult
& RELAYOUT_RES_DRAG_RESIZING_DOCKED) != 0;
final boolean dragResizing = freeformResizing || dockedResizing;
- if ((relayoutResult & WindowManagerGlobal.RELAYOUT_RES_BLAST_SYNC) != 0) {
+ if (mSyncSeqId > mLastSyncSeqId) {
+ mLastSyncSeqId = mSyncSeqId;
if (DEBUG_BLAST) {
Log.d(mTag, "Relayout called with blastSync");
}
reportNextDraw();
- if (isHardwareEnabled()) {
- useBlastSync = true;
- }
}
final boolean surfaceControlChanged =
@@ -3147,12 +3169,9 @@
// done to achieve a more hermetic fix for S, but it's entirely
// possible that checking the most recent value is actually more
// correct here.
- if (!mStopped || wasReportNextDraw) {
- boolean focusChangedDueToTouchMode = ensureTouchModeLocally(
- (relayoutResult&WindowManagerGlobal.RELAYOUT_RES_IN_TOUCH_MODE) != 0);
- if (focusChangedDueToTouchMode || mWidth != host.getMeasuredWidth()
- || mHeight != host.getMeasuredHeight() || dispatchApplyInsets ||
- updatedConfiguration) {
+ if (!mStopped || mReportNextDraw) {
+ if (mWidth != host.getMeasuredWidth() || mHeight != host.getMeasuredHeight()
+ || dispatchApplyInsets || updatedConfiguration) {
int childWidthMeasureSpec = getRootMeasureSpec(mWidth, lp.width,
lp.privateFlags);
int childHeightMeasureSpec = getRootMeasureSpec(mHeight, lp.height,
@@ -3219,7 +3238,7 @@
prepareSurfaces();
}
- final boolean didLayout = layoutRequested && (!mStopped || wasReportNextDraw);
+ final boolean didLayout = layoutRequested && (!mStopped || mReportNextDraw);
boolean triggerGlobalLayoutListener = didLayout
|| mAttachInfo.mRecomputeGlobalAttributes;
if (didLayout) {
@@ -3412,51 +3431,40 @@
mImeFocusController.onTraversal(hasWindowFocus, mWindowAttributes);
- // Remember if we must report the next draw.
- if ((relayoutResult & WindowManagerGlobal.RELAYOUT_RES_FIRST_TIME) != 0) {
+ // If we already got a request for blast sync, then we don't want to unset mSyncBuffer
+ if ((relayoutResult & WindowManagerGlobal.RELAYOUT_RES_FIRST_TIME) != 0
+ && !mReportNextDraw) {
reportNextDraw();
+ mSyncBuffer = false;
}
- boolean cancelDraw = mAttachInfo.mTreeObserver.dispatchOnPreDraw() || !isViewVisible;
- if (mBLASTDrawConsumer != null) {
- useBlastSync = true;
+ boolean cancelAndRedraw = mAttachInfo.mTreeObserver.dispatchOnPreDraw();
+ if (!cancelAndRedraw) {
+ createSyncIfNeeded();
}
- if (!cancelDraw) {
+ if (!isViewVisible) {
+ if (mPendingTransitions != null && mPendingTransitions.size() > 0) {
+ for (int i = 0; i < mPendingTransitions.size(); ++i) {
+ mPendingTransitions.get(i).endChangingAnimations();
+ }
+ mPendingTransitions.clear();
+ }
+
+ if (mSyncBufferCallback != null) {
+ mSyncBufferCallback.onBufferReady(null);
+ }
+ } else if (cancelAndRedraw) {
+ // Try again
+ scheduleTraversals();
+ } else {
if (mPendingTransitions != null && mPendingTransitions.size() > 0) {
for (int i = 0; i < mPendingTransitions.size(); ++i) {
mPendingTransitions.get(i).startChangingAnimations();
}
mPendingTransitions.clear();
}
- performDraw(useBlastSync);
- mNextDrawUseBlastSync = false;
- } else {
- if (isViewVisible) {
- // Try again
- mNextDrawUseBlastSync = useBlastSync;
- scheduleTraversals();
- } else {
- if (mPendingTransitions != null && mPendingTransitions.size() > 0) {
- for (int i = 0; i < mPendingTransitions.size(); ++i) {
- mPendingTransitions.get(i).endChangingAnimations();
- }
- mPendingTransitions.clear();
- }
-
- // We may never draw since it's not visible. Report back that we're finished
- // drawing.
- if (!wasReportNextDraw && mReportNextDraw) {
- mReportNextDraw = false;
- pendingDrawFinished();
- }
-
- // Make sure the consumer is not waiting if the view root was just made invisible.
- if (mBLASTDrawConsumer != null) {
- mBLASTDrawConsumer.accept(null);
- mBLASTDrawConsumer = null;
- }
- }
+ performDraw();
}
if (mAttachInfo.mContentCaptureEvents != null) {
@@ -3465,6 +3473,46 @@
mIsInTraversal = false;
mRelayoutRequested = false;
+
+ if (!cancelAndRedraw) {
+ mReportNextDraw = false;
+ mSyncBufferCallback = null;
+ mSyncBuffer = true;
+ if (mLastSyncId != -1) {
+ mSurfaceSyncer.markSyncReady(mLastSyncId);
+ mLastSyncId = -1;
+ }
+ }
+ }
+
+ private void createSyncIfNeeded() {
+ // Started a sync already.
+ if (mLastSyncId != -1) {
+ return;
+ }
+
+ Consumer<Transaction> syncConsumer = null;
+ if (mBLASTDrawConsumer != null) {
+ syncConsumer = mBLASTDrawConsumer;
+ mBLASTDrawConsumer = null;
+ } else if (mReportNextDraw) {
+ syncConsumer = transaction -> {
+ mSurfaceChangedTransaction.merge(transaction);
+ reportDrawFinished();
+ };
+ }
+
+ if (syncConsumer != null) {
+ final Consumer<Transaction> capturedSyncConsumer = syncConsumer;
+ mLastSyncId = mSurfaceSyncer.setupSync(transaction -> {
+ // Callback will be invoked on executor thread so post to main thread.
+ mHandler.postAtFrontOfQueue(() -> capturedSyncConsumer.accept(transaction));
+ });
+ if (DEBUG_BLAST) {
+ Log.d(mTag, "Setup new sync id=" + mLastSyncId);
+ }
+ mSurfaceSyncer.addToSync(mLastSyncId, mSyncTarget);
+ }
}
private void notifyContentCatpureEvents() {
@@ -4078,57 +4126,13 @@
}
}
- /**
- * A count of the number of calls to pendingDrawFinished we
- * require to notify the WM drawing is complete.
- */
- int mDrawsNeededToReport = 0;
-
- /**
- * Delay notifying WM of draw finished until
- * a balanced call to pendingDrawFinished.
- */
- void drawPending() {
- mDrawsNeededToReport++;
- }
-
- void pendingDrawFinished(Transaction t) {
- if (mDrawsNeededToReport == 0) {
- throw new RuntimeException("Unbalanced drawPending/pendingDrawFinished calls");
- }
-
- if (t != null) {
- if (DEBUG_BLAST) {
- Log.d(mTag, "Merging transaction into main window transaction");
- }
- mSurfaceChangedTransaction.merge(t);
- }
-
- mDrawsNeededToReport--;
- if (mDrawsNeededToReport == 0) {
- reportDrawFinished();
- } else if (DEBUG_BLAST) {
- Log.d(mTag, "pendingDrawFinished. Waiting on draw reported mDrawsNeededToReport="
- + mDrawsNeededToReport);
- }
- }
-
- void pendingDrawFinished() {
- pendingDrawFinished(null);
- }
-
- private void postDrawFinished() {
- mHandler.sendEmptyMessage(MSG_DRAW_FINISHED);
- }
-
private void reportDrawFinished() {
if (DEBUG_BLAST) {
- Log.d(mTag, "reportDrawFinished");
+ Log.d(mTag, "reportDrawFinished " + Debug.getCallers(5));
}
- mDrawsNeededToReport = 0;
try {
- mWindowSession.finishDrawing(mWindow, mSurfaceChangedTransaction);
+ mWindowSession.finishDrawing(mWindow, mSurfaceChangedTransaction, Integer.MAX_VALUE);
} catch (RemoteException e) {
Log.e(mTag, "Unable to report draw finished", e);
mSurfaceChangedTransaction.apply();
@@ -4144,6 +4148,14 @@
return mAttachInfo.mThreadedRenderer != null && mAttachInfo.mThreadedRenderer.isEnabled();
}
+ boolean addToSync(SurfaceSyncer.SyncTarget syncable) {
+ if (mLastSyncId == -1) {
+ return false;
+ }
+ mSurfaceSyncer.addToSync(mLastSyncId, syncable);
+ return true;
+ }
+
private void addFrameCommitCallbackIfNeeded() {
if (!isHardwareEnabled()) {
return;
@@ -4174,188 +4186,81 @@
});
}
- private HardwareRenderer.FrameCommitCallback createFrameCommitCallbackForSync(
- boolean useBlastSync, boolean reportNextDraw, Consumer<Transaction> blastSyncConsumer) {
- return didProduceBuffer -> {
- if (DEBUG_BLAST) {
- Log.d(mTag, "Received frameCommittedCallback "
- + " lastAttemptedDrawFrameNum=" + mRtLastAttemptedDrawFrameNum
- + " didProduceBuffer=" + didProduceBuffer);
- }
-
- // If frame wasn't drawn, clear out the next transaction so it doesn't affect the next
- // draw attempt. The next transaction and transaction complete callback were only set
- // for the current draw attempt.
- final Transaction pendingTransactions;
- if (!didProduceBuffer) {
- mBlastBufferQueue.syncNextTransaction(null);
- // Get the transactions that were sent to mergeWithNextTransaction since the
- // frame didn't draw on this vsync. It's possible the frame will draw later, but
- // it's better to not be sync than to block on a frame that may never come.
- pendingTransactions = mBlastBufferQueue.gatherPendingTransactions(
- mRtLastAttemptedDrawFrameNum);
- if (!useBlastSync && !reportNextDraw) {
- pendingTransactions.apply();
- }
- } else {
- pendingTransactions = null;
- }
- // Post at front of queue so the buffer can be processed immediately and allow RT
- // to continue processing new buffers. If RT tries to process buffers before the sync
- // buffer is applied, the new buffers will not get acquired and could result in a
- // deadlock. UI thread would wait on RT, but RT would be blocked waiting for a free
- // buffer.
- mHandler.postAtFrontOfQueue(() -> {
- if (!didProduceBuffer && useBlastSync) {
- mSurfaceChangedTransaction.merge(pendingTransactions);
- if (blastSyncConsumer != null) {
- blastSyncConsumer.accept(mSurfaceChangedTransaction);
- }
- }
-
- // This is to ensure pendingDrawFinished is only called exactly one time per draw
- // attempt when reportNextDraw is true. Since, we sometimes create a sync
- // transaction callback, the callback will handle calling pendingDrawFinished.
- // However, there are cases where the transaction callback may not be called.
- // 1. If useBlastSync is false, then we know that a sync transaction callback was
- // not created so we won't invoke pendingDrawFinished there.
- // 2. If the draw didn't produce a frame, didProduceBuffer == false, then we know
- // the sync transaction callback will not be invoked even if one was set up.
- if (reportNextDraw && (!didProduceBuffer || !useBlastSync)) {
- pendingDrawFinished();
- }
- });
-
- };
- }
-
@Nullable
- private FrameDrawingCallback createFrameDrawingCallbackIfNeeded(boolean useBlastSync,
- boolean reportNextDraw) {
+ private void registerFrameDrawingCallbackForBlur() {
if (!isHardwareEnabled()) {
- return null;
+ return;
}
final boolean hasBlurUpdates = mBlurRegionAggregator.hasUpdates();
final boolean needsCallbackForBlur = hasBlurUpdates || mBlurRegionAggregator.hasRegions();
- if (!useBlastSync && !needsCallbackForBlur && !reportNextDraw && !mHasPendingTransactions) {
- return null;
- }
-
- final Consumer<SurfaceControl.Transaction> blastSyncConsumer = mBLASTDrawConsumer;
- mBLASTDrawConsumer = null;
-
- if (DEBUG_BLAST) {
- Log.d(mTag, "Creating frameDrawingCallback"
- + " nextDrawUseBlastSync=" + useBlastSync
- + " reportNextDraw=" + reportNextDraw
- + " hasBlurUpdates=" + hasBlurUpdates
- + " hasBlastSyncConsumer=" + (blastSyncConsumer != null)
- + " mHasPendingTransactions=" + mHasPendingTransactions);
+ if (!needsCallbackForBlur) {
+ return;
}
final BackgroundBlurDrawable.BlurRegion[] blurRegionsForFrame =
- needsCallbackForBlur ? mBlurRegionAggregator.getBlurRegionsCopyForRT() : null;
- final boolean hasPendingTransactions = mHasPendingTransactions;
- mHasPendingTransactions = false;
-
+ mBlurRegionAggregator.getBlurRegionsCopyForRT();
// The callback will run on the render thread.
- return new FrameDrawingCallback() {
+ registerRtFrameCallback((frame) -> mBlurRegionAggregator
+ .dispatchBlurTransactionIfNeeded(frame, blurRegionsForFrame, hasBlurUpdates));
+ }
+
+ private void registerCallbackForPendingTransactions() {
+ registerRtFrameCallback(new FrameDrawingCallback() {
+ @Override
+ public HardwareRenderer.FrameCommitCallback onFrameDraw(int syncResult, long frame) {
+ if ((syncResult
+ & (SYNC_LOST_SURFACE_REWARD_IF_FOUND | SYNC_CONTEXT_IS_STOPPED)) != 0) {
+ mBlastBufferQueue.applyPendingTransactions(frame);
+ return null;
+ }
+
+ return didProduceBuffer -> {
+ if (!didProduceBuffer) {
+ mBlastBufferQueue.applyPendingTransactions(frame);
+ }
+ };
+
+ }
+
@Override
public void onFrameDraw(long frame) {
}
-
- @Override
- public HardwareRenderer.FrameCommitCallback onFrameDraw(int syncResult, long frame) {
- if (DEBUG_BLAST) {
- Log.d(mTag,
- "Received frameDrawingCallback syncResult=" + syncResult + " frameNum="
- + frame + ".");
- }
-
- mRtLastAttemptedDrawFrameNum = frame;
-
- if (needsCallbackForBlur) {
- mBlurRegionAggregator.dispatchBlurTransactionIfNeeded(frame,
- blurRegionsForFrame, hasBlurUpdates);
- }
-
- if (mBlastBufferQueue == null) {
- return null;
- }
-
- if (!useBlastSync && !reportNextDraw && !hasPendingTransactions) {
- return null;
- }
-
- // If the syncResults are SYNC_LOST_SURFACE_REWARD_IF_FOUND or
- // SYNC_CONTEXT_IS_STOPPED it means nothing will draw. There's no need to set up
- // any blast sync or commit callback, and the code should directly call
- // pendingDrawFinished.
- if ((syncResult
- & (SYNC_LOST_SURFACE_REWARD_IF_FOUND | SYNC_CONTEXT_IS_STOPPED)) != 0) {
- if (reportNextDraw) {
- mHandler.postAtFrontOfQueue(() -> pendingDrawFinished());
- }
- return null;
- }
-
- if (DEBUG_BLAST) {
- Log.d(mTag, "Setting up sync and frameCommitCallback");
- }
-
- if (useBlastSync) {
- // Frame callbacks will always occur after submitting draw requests and before
- // the draw actually occurs. This will ensure that we set the next transaction
- // for the frame that's about to get drawn and not on a previous frame.
- mBlastBufferQueue.syncNextTransaction(
- t -> {
- mHandler.postAtFrontOfQueue(() -> {
- mSurfaceChangedTransaction.merge(t);
- if (blastSyncConsumer != null) {
- blastSyncConsumer.accept(mSurfaceChangedTransaction);
- }
-
- if (reportNextDraw) {
- pendingDrawFinished();
- }
- });
- });
- }
-
- return createFrameCommitCallbackForSync(useBlastSync, reportNextDraw,
- blastSyncConsumer);
- }
- };
+ });
}
- private void performDraw(boolean useBlastSync) {
+ private void performDraw() {
if (mAttachInfo.mDisplayState == Display.STATE_OFF && !mReportNextDraw) {
return;
} else if (mView == null) {
return;
}
- final boolean fullRedrawNeeded = mFullRedrawNeeded || mReportNextDraw || useBlastSync;
+ final boolean fullRedrawNeeded = mFullRedrawNeeded || mSyncBufferCallback != null;
mFullRedrawNeeded = false;
mIsDrawing = true;
Trace.traceBegin(Trace.TRACE_TAG_VIEW, "draw");
- FrameDrawingCallback frameDrawingCallback = createFrameDrawingCallbackIfNeeded(useBlastSync,
- mReportNextDraw);
- if (frameDrawingCallback != null) {
- mAttachInfo.mThreadedRenderer.registerRtFrameCallback(frameDrawingCallback);
- }
+ registerFrameDrawingCallbackForBlur();
addFrameCommitCallbackIfNeeded();
- boolean usingAsyncReport = isHardwareEnabled() && (useBlastSync || mReportNextDraw);
+
+ boolean usingAsyncReport = isHardwareEnabled() && mSyncBufferCallback != null;
+ if (usingAsyncReport) {
+ registerCallbacksForSync(mSyncBuffer, mSyncBufferCallback);
+ } else if (mHasPendingTransactions) {
+ // These callbacks are only needed if there's no sync involved and there were calls to
+ // applyTransactionOnDraw. These callbacks check if the draw failed for any reason and
+ // apply those transactions directly so they don't get stuck forever.
+ registerCallbackForPendingTransactions();
+ }
+ mHasPendingTransactions = false;
try {
boolean canUseAsync = draw(fullRedrawNeeded);
if (usingAsyncReport && !canUseAsync) {
mAttachInfo.mThreadedRenderer.setFrameCallback(null);
usingAsyncReport = false;
- mAttachInfo.mThreadedRenderer.unregisterRtFrameCallback(frameDrawingCallback);
}
} finally {
mIsDrawing = false;
@@ -4373,7 +4278,6 @@
}
if (mReportNextDraw) {
- mReportNextDraw = false;
// if we're using multi-thread renderer, wait for the window frame draws
if (mWindowDrawCountDown != null) {
@@ -4394,7 +4298,11 @@
}
if (mSurfaceHolder != null && mSurface.isValid()) {
- SurfaceCallbackHelper sch = new SurfaceCallbackHelper(this::postDrawFinished);
+ final SurfaceSyncer.SyncBufferCallback syncBufferCallback = mSyncBufferCallback;
+ SurfaceCallbackHelper sch = new SurfaceCallbackHelper(() ->
+ mHandler.post(() -> syncBufferCallback.onBufferReady(null)));
+ mSyncBufferCallback = null;
+
SurfaceHolder.Callback callbacks[] = mSurfaceHolder.getCallbacks();
sch.dispatchSurfaceRedrawNeededAsync(mSurfaceHolder, callbacks);
@@ -4402,9 +4310,11 @@
if (mAttachInfo.mThreadedRenderer != null) {
mAttachInfo.mThreadedRenderer.fence();
}
- pendingDrawFinished();
}
}
+ if (mSyncBufferCallback != null && !usingAsyncReport) {
+ mSyncBufferCallback.onBufferReady(null);
+ }
if (mPerformContentCapture) {
performContentCaptureInitialReport();
}
@@ -5413,7 +5323,6 @@
private static final int MSG_REQUEST_KEYBOARD_SHORTCUTS = 26;
private static final int MSG_UPDATE_POINTER_ICON = 27;
private static final int MSG_POINTER_CAPTURE_CHANGED = 28;
- private static final int MSG_DRAW_FINISHED = 29;
private static final int MSG_INSETS_CHANGED = 30;
private static final int MSG_INSETS_CONTROL_CHANGED = 31;
private static final int MSG_SYSTEM_GESTURE_EXCLUSION_CHANGED = 32;
@@ -5476,8 +5385,6 @@
return "MSG_UPDATE_POINTER_ICON";
case MSG_POINTER_CAPTURE_CHANGED:
return "MSG_POINTER_CAPTURE_CHANGED";
- case MSG_DRAW_FINISHED:
- return "MSG_DRAW_FINISHED";
case MSG_INSETS_CHANGED:
return "MSG_INSETS_CHANGED";
case MSG_INSETS_CONTROL_CHANGED:
@@ -5710,9 +5617,6 @@
final boolean hasCapture = msg.arg1 != 0;
handlePointerCaptureChanged(hasCapture);
} break;
- case MSG_DRAW_FINISHED: {
- pendingDrawFinished();
- } break;
case MSG_SYSTEM_GESTURE_EXCLUSION_CHANGED: {
systemGestureExclusionChanged();
} break;
@@ -8071,7 +7975,8 @@
requestedWidth, requestedHeight, viewVisibility,
insetsPending ? WindowManagerGlobal.RELAYOUT_INSETS_PENDING : 0,
mTmpFrames, mPendingMergedConfiguration, mSurfaceControl, mTempInsets,
- mTempControls);
+ mTempControls, mRelayoutBundle);
+ mSyncSeqId = mRelayoutBundle.getInt("seqid");
final int transformHint = SurfaceControl.rotationToBufferTransform(
(mDisplayInstallOrientation + mDisplay.getRotation()) % 4);
@@ -8497,7 +8402,7 @@
if ((relayoutWindow(mWindowAttributes, viewVisibility, false)
& WindowManagerGlobal.RELAYOUT_RES_FIRST_TIME) != 0) {
mWindowSession.finishDrawing(
- mWindow, null /* postDrawTransaction */);
+ mWindow, null /* postDrawTransaction */, Integer.MAX_VALUE);
}
} catch (RemoteException e) {
}
@@ -8571,7 +8476,7 @@
@UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
private void dispatchResized(ClientWindowFrames frames, boolean reportDraw,
MergedConfiguration mergedConfiguration, boolean forceLayout,
- boolean alwaysConsumeSystemBars, int displayId) {
+ boolean alwaysConsumeSystemBars, int displayId, int seqId) {
final Rect frame = frames.frame;
final Rect backDropFrame = frames.backdropFrame;
if (DEBUG_LAYOUT) Log.v(mTag, "Resizing " + this + ": frame=" + frame.toShortString()
@@ -8602,6 +8507,7 @@
args.argi1 = forceLayout ? 1 : 0;
args.argi2 = alwaysConsumeSystemBars ? 1 : 0;
args.argi3 = displayId;
+ args.argi4 = seqId;
msg.obj = args;
mHandler.sendMessage(msg);
}
@@ -9893,8 +9799,8 @@
}
private void reportNextDraw() {
- if (mReportNextDraw == false) {
- drawPending();
+ if (DEBUG_BLAST) {
+ Log.d(mTag, "reportNextDraw " + Debug.getCallers(5));
}
mReportNextDraw = true;
}
@@ -9905,9 +9811,14 @@
* This method is only supposed to be used to speed up the interaction from SystemUI and window
* manager when waiting for the first frame to be drawn when turning on the screen. DO NOT USE
* unless you fully understand this interaction.
+ *
+ * @param syncBuffer If true, the transaction that contains the buffer from the draw should be
+ * sent to system to be synced. If false, VRI will not try to sync the buffer,
+ * but only report back that a buffer was drawn.
* @hide
*/
- public void setReportNextDraw() {
+ public void setReportNextDraw(boolean syncBuffer) {
+ mSyncBuffer = syncBuffer;
reportNextDraw();
invalidate();
}
@@ -9986,11 +9897,11 @@
@Override
public void resized(ClientWindowFrames frames, boolean reportDraw,
MergedConfiguration mergedConfiguration, boolean forceLayout,
- boolean alwaysConsumeSystemBars, int displayId) {
+ boolean alwaysConsumeSystemBars, int displayId, int seqId) {
final ViewRootImpl viewAncestor = mViewAncestor.get();
if (viewAncestor != null) {
viewAncestor.dispatchResized(frames, reportDraw, mergedConfiguration, forceLayout,
- alwaysConsumeSystemBars, displayId);
+ alwaysConsumeSystemBars, displayId, seqId);
}
}
@@ -10908,7 +10819,7 @@
}
};
mOnBackInvokedDispatcher.registerOnBackInvokedCallback(
- mCompatOnBackInvokedCallback, OnBackInvokedDispatcher.PRIORITY_DEFAULT);
+ OnBackInvokedDispatcher.PRIORITY_DEFAULT, mCompatOnBackInvokedCallback);
}
private void unregisterCompatOnBackInvokedCallback() {
@@ -10933,14 +10844,15 @@
return mWindowSession;
}
- private void registerCallbacksForSync(
+ private void registerCallbacksForSync(boolean syncBuffer,
final SurfaceSyncer.SyncBufferCallback syncBufferCallback) {
if (!isHardwareEnabled()) {
- // TODO: correctly handle when hardware disabled
- syncBufferCallback.onBufferReady(null);
return;
}
+ if (DEBUG_BLAST) {
+ Log.d(mTag, "registerCallbacksForSync syncBuffer=" + syncBuffer);
+ }
mAttachInfo.mThreadedRenderer.registerRtFrameCallback(new FrameDrawingCallback() {
@Override
public void onFrameDraw(long frame) {
@@ -10969,7 +10881,9 @@
Log.d(mTag, "Setting up sync and frameCommitCallback");
}
- mBlastBufferQueue.syncNextTransaction(t -> syncBufferCallback.onBufferReady(t));
+ if (syncBuffer) {
+ mBlastBufferQueue.syncNextTransaction(syncBufferCallback::onBufferReady);
+ }
return didProduceBuffer -> {
if (DEBUG_BLAST) {
@@ -10983,18 +10897,40 @@
// were only set for the current draw attempt.
if (!didProduceBuffer) {
mBlastBufferQueue.syncNextTransaction(null);
+
// Gather the transactions that were sent to mergeWithNextTransaction
// since the frame didn't draw on this vsync. It's possible the frame will
// draw later, but it's better to not be sync than to block on a frame that
// may never come.
syncBufferCallback.onBufferReady(
mBlastBufferQueue.gatherPendingTransactions(frame));
+ return;
+ }
+
+ // If we didn't request to sync a buffer, then we won't get the
+ // syncNextTransaction callback. Instead, just report back to the Syncer so it
+ // knows that this sync request is complete.
+ if (!syncBuffer) {
+ syncBufferCallback.onBufferReady(null);
}
};
}
});
}
- public final SurfaceSyncer.SyncTarget mSyncTarget =
- syncBufferCallback -> registerCallbacksForSync(syncBufferCallback);
+ public final SurfaceSyncer.SyncTarget mSyncTarget = this::readyToSync;
+
+ private void readyToSync(SurfaceSyncer.SyncBufferCallback syncBufferCallback) {
+ if (mSyncBufferCallback != null) {
+ Log.d(mTag, "Already set sync for the next draw.");
+ mSyncBufferCallback.onBufferReady(null);
+ }
+ if (DEBUG_BLAST) {
+ Log.d(mTag, "Setting syncFrameCallback");
+ }
+ mSyncBufferCallback = syncBufferCallback;
+ if (!mIsInTraversal && !mTraversalScheduled) {
+ scheduleTraversals();
+ }
+ }
}
diff --git a/core/java/android/view/WindowLayout.java b/core/java/android/view/WindowLayout.java
index ad9f21b..a3b1313 100644
--- a/core/java/android/view/WindowLayout.java
+++ b/core/java/android/view/WindowLayout.java
@@ -42,6 +42,7 @@
import android.graphics.Point;
import android.graphics.Rect;
import android.util.Log;
+import android.window.ClientWindowFrames;
/**
* Computes window frames.
@@ -56,15 +57,17 @@
private final Rect mTempDisplayCutoutSafeExceptMaybeBarsRect = new Rect();
private final Rect mTempRect = new Rect();
- public boolean computeFrames(WindowManager.LayoutParams attrs, InsetsState state,
+ public void computeFrames(WindowManager.LayoutParams attrs, InsetsState state,
Rect displayCutoutSafe, Rect windowBounds, @WindowingMode int windowingMode,
int requestedWidth, int requestedHeight, InsetsVisibilities requestedVisibilities,
- Rect attachedWindowFrame, float compatScale, Rect outDisplayFrame, Rect outParentFrame,
- Rect outFrame) {
+ Rect attachedWindowFrame, float compatScale, ClientWindowFrames outFrames) {
final int type = attrs.type;
final int fl = attrs.flags;
final int pfl = attrs.privateFlags;
final boolean layoutInScreen = (fl & FLAG_LAYOUT_IN_SCREEN) == FLAG_LAYOUT_IN_SCREEN;
+ final Rect outDisplayFrame = outFrames.displayFrame;
+ final Rect outParentFrame = outFrames.parentFrame;
+ final Rect outFrame = outFrames.frame;
// Compute bounds restricted by insets
final Insets insets = state.calculateInsets(windowBounds, attrs.getFitInsetsTypes(),
@@ -95,7 +98,7 @@
final DisplayCutout cutout = state.getDisplayCutout();
final Rect displayCutoutSafeExceptMaybeBars = mTempDisplayCutoutSafeExceptMaybeBarsRect;
displayCutoutSafeExceptMaybeBars.set(displayCutoutSafe);
- boolean clippedByDisplayCutout = false;
+ outFrames.isParentFrameClippedByDisplayCutout = false;
if (cutoutMode != LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS && !cutout.isEmpty()) {
// Ensure that windows with a non-ALWAYS display cutout mode are laid out in
// the cutout safe zone.
@@ -158,7 +161,7 @@
if (!attachedInParent && !floatingInScreenWindow) {
mTempRect.set(outParentFrame);
outParentFrame.intersectUnchecked(displayCutoutSafeExceptMaybeBars);
- clippedByDisplayCutout = !mTempRect.equals(outParentFrame);
+ outFrames.isParentFrameClippedByDisplayCutout = !mTempRect.equals(outParentFrame);
}
outDisplayFrame.intersectUnchecked(displayCutoutSafeExceptMaybeBars);
}
@@ -287,9 +290,7 @@
}
if (DEBUG) Log.d(TAG, "computeWindowFrames " + attrs.getTitle()
- + " outFrame=" + outFrame.toShortString()
- + " outParentFrame=" + outParentFrame.toShortString()
- + " outDisplayFrame=" + outDisplayFrame.toShortString()
+ + " outFrames=" + outFrames
+ " windowBounds=" + windowBounds.toShortString()
+ " attachedWindowFrame=" + (attachedWindowFrame != null
? attachedWindowFrame.toShortString()
@@ -302,8 +303,6 @@
+ " attrs=" + attrs
+ " state=" + state
+ " requestedVisibilities=" + requestedVisibilities);
-
- return clippedByDisplayCutout;
}
public static void computeSurfaceSize(WindowManager.LayoutParams attrs, Rect maxBounds,
diff --git a/core/java/android/view/WindowManagerGlobal.java b/core/java/android/view/WindowManagerGlobal.java
index 2dc5fbd..55c9f0f 100644
--- a/core/java/android/view/WindowManagerGlobal.java
+++ b/core/java/android/view/WindowManagerGlobal.java
@@ -60,55 +60,41 @@
private static boolean sUseBLASTAdapter = false;
/**
- * The user is navigating with keys (not the touch screen), so
- * navigational focus should be shown.
- */
- public static final int RELAYOUT_RES_IN_TOUCH_MODE = 0x1;
-
- /**
* This is the first time the window is being drawn,
* so the client must call drawingFinished() when done
*/
- public static final int RELAYOUT_RES_FIRST_TIME = 0x2;
+ public static final int RELAYOUT_RES_FIRST_TIME = 1;
/**
* The window manager has changed the surface from the last call.
*/
- public static final int RELAYOUT_RES_SURFACE_CHANGED = 0x4;
+ public static final int RELAYOUT_RES_SURFACE_CHANGED = 1 << 1;
/**
* The window is being resized by dragging on the docked divider. The client should render
* at (0, 0) and extend its background to the background frame passed into
* {@link IWindow#resized}.
*/
- public static final int RELAYOUT_RES_DRAG_RESIZING_DOCKED = 0x8;
+ public static final int RELAYOUT_RES_DRAG_RESIZING_DOCKED = 1 << 2;
/**
* The window is being resized by dragging one of the window corners,
* in this case the surface would be fullscreen-sized. The client should
* render to the actual frame location (instead of (0,curScrollY)).
*/
- public static final int RELAYOUT_RES_DRAG_RESIZING_FREEFORM = 0x10;
+ public static final int RELAYOUT_RES_DRAG_RESIZING_FREEFORM = 1 << 3;
/**
* The window manager has changed the size of the surface from the last call.
*/
- public static final int RELAYOUT_RES_SURFACE_RESIZED = 0x20;
+ public static final int RELAYOUT_RES_SURFACE_RESIZED = 1 << 4;
/**
* In multi-window we force show the system bars. Because we don't want that the surface size
* changes in this mode, we instead have a flag whether the system bar sizes should always be
* consumed, so the app is treated like there is no virtual system bars at all.
*/
- public static final int RELAYOUT_RES_CONSUME_ALWAYS_SYSTEM_BARS = 0x40;
-
- /**
- * This flag indicates the client should not directly submit it's next frame,
- * but instead should pass it in the postDrawTransaction of
- * {@link WindowManagerService#finishDrawing}. This is used by the WM
- * BLASTSyncEngine to synchronize rendering of multiple windows.
- */
- public static final int RELAYOUT_RES_BLAST_SYNC = 0x80;
+ public static final int RELAYOUT_RES_CONSUME_ALWAYS_SYSTEM_BARS = 1 << 5;
/**
* Flag for relayout: the client will be later giving
diff --git a/core/java/android/view/WindowlessWindowManager.java b/core/java/android/view/WindowlessWindowManager.java
index a270c92..06588b2 100644
--- a/core/java/android/view/WindowlessWindowManager.java
+++ b/core/java/android/view/WindowlessWindowManager.java
@@ -22,6 +22,7 @@
import android.graphics.Rect;
import android.graphics.Region;
import android.os.Binder;
+import android.os.Bundle;
import android.os.IBinder;
import android.os.RemoteCallback;
import android.os.RemoteException;
@@ -217,9 +218,13 @@
throw new IllegalArgumentException(
"Invalid window token (never added or removed already)");
}
+ removeSurface(state.mSurfaceControl);
+ }
+ /** Separate from {@link #remove} so that subclasses can put removal on a sync transaction. */
+ protected void removeSurface(SurfaceControl sc) {
try (SurfaceControl.Transaction t = new SurfaceControl.Transaction()) {
- t.remove(state.mSurfaceControl).apply();
+ t.remove(sc).apply();
}
}
@@ -277,7 +282,7 @@
int requestedWidth, int requestedHeight, int viewFlags, int flags,
ClientWindowFrames outFrames, MergedConfiguration mergedConfiguration,
SurfaceControl outSurfaceControl, InsetsState outInsetsState,
- InsetsSourceControl[] outActiveControls) {
+ InsetsSourceControl[] outActiveControls, Bundle outSyncSeqIdBundle) {
final State state;
synchronized (this) {
state = mStateForWindow.get(window.asBinder());
@@ -327,8 +332,7 @@
outInsetsState.set(mInsetsState);
}
- // Include whether the window is in touch mode.
- return isInTouchMode() ? WindowManagerGlobal.RELAYOUT_RES_IN_TOUCH_MODE : 0;
+ return 0;
}
@Override
@@ -354,7 +358,7 @@
@Override
public void finishDrawing(android.view.IWindow window,
- android.view.SurfaceControl.Transaction postDrawTransaction) {
+ android.view.SurfaceControl.Transaction postDrawTransaction, int seqId) {
synchronized (this) {
final ResizeCompleteCallback c =
mResizeCompletionForWindow.get(window.asBinder());
diff --git a/core/java/android/view/autofill/AutofillManager.java b/core/java/android/view/autofill/AutofillManager.java
index a8cc114..2c81eb1 100644
--- a/core/java/android/view/autofill/AutofillManager.java
+++ b/core/java/android/view/autofill/AutofillManager.java
@@ -16,9 +16,9 @@
package android.view.autofill;
-import static android.service.autofill.FillRequest.FLAG_ACTIVITY_START;
import static android.service.autofill.FillRequest.FLAG_MANUAL_REQUEST;
import static android.service.autofill.FillRequest.FLAG_PASSWORD_INPUT_TYPE;
+import static android.service.autofill.FillRequest.FLAG_SUPPORTS_FILL_DIALOG;
import static android.service.autofill.FillRequest.FLAG_VIEW_NOT_FOCUSED;
import static android.view.ContentInfo.SOURCE_AUTOFILL;
import static android.view.autofill.Helper.sDebug;
@@ -1118,7 +1118,7 @@
return;
}
- int flags = FLAG_ACTIVITY_START;
+ int flags = FLAG_SUPPORTS_FILL_DIALOG;
flags |= FLAG_VIEW_NOT_FOCUSED;
notifyViewEntered(view, flags);
}
@@ -3121,17 +3121,19 @@
}
/**
- * If autofill suggestions for a dialog-style UI are available for {@code view}, shows a dialog
- * allowing the user to select a suggestion and returns {@code true}.
+ * If autofill suggestions for a
+ * <a href="{@docRoot}reference/android/service/autofill/Dataset.html#FillDialogUI">
+ * dialog-style UI</a> are available for {@code view}, shows a dialog allowing the user to
+ * select a suggestion and returns {@code true}.
* <p>
* The dialog may not be available if the autofill service does not support it, or if the
* autofill request has not returned a response yet.
* <p>
- * It is recommended to call this method the first time a user focuses on an autofill-able form,
- * and to avoid showing the input method if the dialog is shown. If this method returns
- * {@code false}, you should then instead show the input method (assuming that is how the
- * view normally handles the focus event). If the user re-focuses on the view, you should not
- * call this method again so as to not disrupt usage of the input method.
+ * It is recommended apps to call this method the first time a user focuses on
+ * an autofill-able form, and to avoid showing the input method if the dialog is shown. If
+ * this method returns {@code false}, you should then instead show the input method (assuming
+ * that is how the view normally handles the focus event). If the user re-focuses on the view,
+ * you should not call this method again so as to not disrupt usage of the input method.
*
* @param view the view for which to show autofill suggestions. This is typically a view
* receiving a focus event. The autofill suggestions shown will include content for
diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java
index b076d39..3c8fcb9 100644
--- a/core/java/android/widget/TextView.java
+++ b/core/java/android/widget/TextView.java
@@ -788,7 +788,8 @@
private Layout mLayout;
private boolean mLocalesChanged = false;
private int mTextSizeUnit = -1;
- private LineBreakConfig mLineBreakConfig = new LineBreakConfig();
+ private int mLineBreakStyle = DEFAULT_LINE_BREAK_STYLE;
+ private int mLineBreakWordStyle = DEFAULT_LINE_BREAK_WORD_STYLE;
// This is used to reflect the current user preference for changing font weight and making text
// more bold.
@@ -1457,13 +1458,12 @@
break;
case com.android.internal.R.styleable.TextView_lineBreakStyle:
- mLineBreakConfig.setLineBreakStyle(
- a.getInt(attr, LineBreakConfig.LINE_BREAK_STYLE_NONE));
+ mLineBreakStyle = a.getInt(attr, LineBreakConfig.LINE_BREAK_STYLE_NONE);
break;
case com.android.internal.R.styleable.TextView_lineBreakWordStyle:
- mLineBreakConfig.setLineBreakWordStyle(
- a.getInt(attr, LineBreakConfig.LINE_BREAK_WORD_STYLE_NONE));
+ mLineBreakWordStyle = a.getInt(attr,
+ LineBreakConfig.LINE_BREAK_WORD_STYLE_NONE);
break;
case com.android.internal.R.styleable.TextView_autoSizeTextType:
@@ -4301,13 +4301,12 @@
@LineBreakConfig.LineBreakStyle int lineBreakStyle,
@LineBreakConfig.LineBreakWordStyle int lineBreakWordStyle) {
boolean updated = false;
- if (isLineBreakStyleSpecified && mLineBreakConfig.getLineBreakStyle() != lineBreakStyle) {
- mLineBreakConfig.setLineBreakStyle(lineBreakStyle);
+ if (isLineBreakStyleSpecified && mLineBreakStyle != lineBreakStyle) {
+ mLineBreakStyle = lineBreakStyle;
updated = true;
}
- if (isLineBreakWordStyleSpecified
- && mLineBreakConfig.getLineBreakWordStyle() != lineBreakWordStyle) {
- mLineBreakConfig.setLineBreakWordStyle(lineBreakWordStyle);
+ if (isLineBreakWordStyleSpecified && mLineBreakWordStyle != lineBreakWordStyle) {
+ mLineBreakWordStyle = lineBreakWordStyle;
updated = true;
}
if (updated && mLayout != null) {
@@ -4871,50 +4870,72 @@
}
/**
- * Sets line break configuration indicates which strategy needs to be used when calculating the
- * text wrapping.
- * <P>
- * There are two types of line break rules that can be configured at the same time. One is
- * line break style(lb) and the other is line break word style(lw). The line break style
- * affects rule-based breaking. The line break word style affects dictionary-based breaking
- * and provide phrase-based breaking opportunities. There are several types for the
- * line break style:
+ * Set the line break style for text wrapping.
+ *
+ * The line break style to indicates the line break strategies can be used when
+ * calculating the text wrapping. The line break style affects rule-based breaking. It
+ * specifies the strictness of line-breaking rules.
+ * There are several types for the line break style:
* {@link LineBreakConfig#LINE_BREAK_STYLE_LOOSE},
* {@link LineBreakConfig#LINE_BREAK_STYLE_NORMAL} and
- * {@link LineBreakConfig#LINE_BREAK_STYLE_STRICT}.
- * The type for the line break word style is
- * {@link LineBreakConfig#LINE_BREAK_WORD_STYLE_PHRASE}.
- * The default values of the line break style and the line break word style are
- * {@link LineBreakConfig#LINE_BREAK_STYLE_NONE} and
- * {@link LineBreakConfig#LINE_BREAK_WORD_STYLE_NONE} respectively, indicating that no line
- * breaking rules are specified.
- * See <a href="https://drafts.csswg.org/css-text/#line-break-property">
+ * {@link LineBreakConfig#LINE_BREAK_STYLE_STRICT}. The default values of the line break style
+ * is {@link LineBreakConfig#LINE_BREAK_STYLE_NONE}, indicating no breaking rule is specified.
+ * See <a href="https://www.w3.org/TR/css-text-3/#line-break-property">
* the line-break property</a>
*
- * @param lineBreakConfig the line break config for text wrapping.
+ * @param lineBreakStyle the line break style for the text.
*/
- public void setLineBreakConfig(@NonNull LineBreakConfig lineBreakConfig) {
- Objects.requireNonNull(lineBreakConfig);
- if (mLineBreakConfig.equals(lineBreakConfig)) {
- return;
- }
- mLineBreakConfig.set(lineBreakConfig);
- if (mLayout != null) {
- nullLayouts();
- requestLayout();
- invalidate();
+ public void setLineBreakStyle(@LineBreakConfig.LineBreakStyle int lineBreakStyle) {
+ if (mLineBreakStyle != lineBreakStyle) {
+ mLineBreakStyle = lineBreakStyle;
+ if (mLayout != null) {
+ nullLayouts();
+ requestLayout();
+ invalidate();
+ }
}
}
/**
- * Get the current line break configuration for text wrapping.
+ * Set the line break word style for text wrapping.
*
- * @return the current line break configuration to be used for text wrapping.
+ * The line break word style affects dictionary-based breaking and provide phrase-based
+ * breaking opportunities. The type for the line break word style is
+ * {@link LineBreakConfig#LINE_BREAK_WORD_STYLE_PHRASE}. The default values of the line break
+ * word style is {@link LineBreakConfig#LINE_BREAK_WORD_STYLE_NONE}, indicating no breaking rule
+ * is specified.
+ * See <a href="https://www.w3.org/TR/css-text-3/#word-break-property">
+ * the word-break property</a>
+ *
+ * @param lineBreakWordStyle the line break word style for the tet
*/
- public @NonNull LineBreakConfig getLineBreakConfig() {
- LineBreakConfig lbConfig = new LineBreakConfig();
- lbConfig.set(mLineBreakConfig);
- return lbConfig;
+ public void setLineBreakWordStyle(@LineBreakConfig.LineBreakWordStyle int lineBreakWordStyle) {
+ if (mLineBreakWordStyle != lineBreakWordStyle) {
+ mLineBreakWordStyle = lineBreakWordStyle;
+ if (mLayout != null) {
+ nullLayouts();
+ requestLayout();
+ invalidate();
+ }
+ }
+ }
+
+ /**
+ * Get the current line break style for text wrapping.
+ *
+ * @return the current line break style to be used for text wrapping.
+ */
+ public @LineBreakConfig.LineBreakStyle int getLineBreakStyle() {
+ return mLineBreakStyle;
+ }
+
+ /**
+ * Get the current line word break style for text wrapping.
+ *
+ * @return the current line break word style to be used for text wrapping.
+ */
+ public @LineBreakConfig.LineBreakWordStyle int getLineBreakWordStyle() {
+ return mLineBreakWordStyle;
}
/**
@@ -4924,7 +4945,8 @@
* @see PrecomputedText
*/
public @NonNull PrecomputedText.Params getTextMetricsParams() {
- return new PrecomputedText.Params(new TextPaint(mTextPaint), mLineBreakConfig,
+ return new PrecomputedText.Params(new TextPaint(mTextPaint),
+ LineBreakConfig.getLineBreakConfig(mLineBreakStyle, mLineBreakWordStyle),
getTextDirectionHeuristic(),
mBreakStrategy, mHyphenationFrequency);
}
@@ -4941,13 +4963,9 @@
mTextDir = params.getTextDirection();
mBreakStrategy = params.getBreakStrategy();
mHyphenationFrequency = params.getHyphenationFrequency();
- if (params.getLineBreakConfig() != null) {
- mLineBreakConfig.set(params.getLineBreakConfig());
- } else {
- // Set default value if the line break config in the PrecomputedText.Params is null.
- mLineBreakConfig.setLineBreakStyle(DEFAULT_LINE_BREAK_STYLE);
- mLineBreakConfig.setLineBreakWordStyle(DEFAULT_LINE_BREAK_WORD_STYLE);
- }
+ LineBreakConfig lineBreakConfig = params.getLineBreakConfig();
+ mLineBreakStyle = lineBreakConfig.getLineBreakStyle();
+ mLineBreakWordStyle = lineBreakConfig.getLineBreakWordStyle();
if (mLayout != null) {
nullLayouts();
requestLayout();
@@ -6486,7 +6504,8 @@
}
final @PrecomputedText.Params.CheckResultUsableResult int checkResult =
precomputed.getParams().checkResultUsable(getPaint(), mTextDir, mBreakStrategy,
- mHyphenationFrequency, mLineBreakConfig);
+ mHyphenationFrequency, LineBreakConfig.getLineBreakConfig(
+ mLineBreakStyle, mLineBreakWordStyle));
switch (checkResult) {
case PrecomputedText.Params.UNUSABLE:
throw new IllegalArgumentException(
@@ -9383,7 +9402,8 @@
.setHyphenationFrequency(mHyphenationFrequency)
.setJustificationMode(mJustificationMode)
.setMaxLines(mMaxMode == LINES ? mMaximum : Integer.MAX_VALUE)
- .setLineBreakConfig(mLineBreakConfig);
+ .setLineBreakConfig(LineBreakConfig.getLineBreakConfig(
+ mLineBreakStyle, mLineBreakWordStyle));
if (shouldEllipsize) {
builder.setEllipsize(mEllipsize)
.setEllipsizedWidth(ellipsisWidth);
@@ -9498,7 +9518,8 @@
.setHyphenationFrequency(mHyphenationFrequency)
.setJustificationMode(mJustificationMode)
.setMaxLines(mMaxMode == LINES ? mMaximum : Integer.MAX_VALUE)
- .setLineBreakConfig(mLineBreakConfig);
+ .setLineBreakConfig(LineBreakConfig.getLineBreakConfig(
+ mLineBreakStyle, mLineBreakWordStyle));
if (shouldEllipsize) {
builder.setEllipsize(effectiveEllipsize)
.setEllipsizedWidth(ellipsisWidth);
@@ -9866,7 +9887,8 @@
.setJustificationMode(getJustificationMode())
.setMaxLines(mMaxMode == LINES ? mMaximum : Integer.MAX_VALUE)
.setTextDirection(getTextDirectionHeuristic())
- .setLineBreakConfig(mLineBreakConfig);
+ .setLineBreakConfig(LineBreakConfig.getLineBreakConfig(
+ mLineBreakStyle, mLineBreakWordStyle));
final StaticLayout layout = layoutBuilder.build();
diff --git a/core/java/android/window/ClientWindowFrames.java b/core/java/android/window/ClientWindowFrames.java
index acf9882..5b915cc 100644
--- a/core/java/android/window/ClientWindowFrames.java
+++ b/core/java/android/window/ClientWindowFrames.java
@@ -27,47 +27,55 @@
*/
public class ClientWindowFrames implements Parcelable {
/** The actual window bounds. */
- public final @NonNull Rect frame;
+ public final @NonNull Rect frame = new Rect();
/**
* The container frame that is usually the same as display size. It may exclude the area of
* insets if the window layout parameter has specified fit-insets-sides.
*/
- public final @NonNull Rect displayFrame;
+ public final @NonNull Rect displayFrame = new Rect();
+
+ /**
+ * The frame to be referenced while applying gravity and MATCH_PARENT.
+ */
+ public final @NonNull Rect parentFrame = new Rect();
/** The background area while the window is resizing. */
- public final @NonNull Rect backdropFrame;
+ public final @NonNull Rect backdropFrame = new Rect();
+
+ public boolean isParentFrameClippedByDisplayCutout;
public ClientWindowFrames() {
- frame = new Rect();
- displayFrame = new Rect();
- backdropFrame = new Rect();
}
public ClientWindowFrames(ClientWindowFrames other) {
- frame = new Rect(other.frame);
- displayFrame = new Rect(other.displayFrame);
- backdropFrame = new Rect(other.backdropFrame);
+ frame.set(other.frame);
+ displayFrame.set(other.displayFrame);
+ parentFrame.set(other.parentFrame);
+ backdropFrame.set(other.backdropFrame);
+ isParentFrameClippedByDisplayCutout = other.isParentFrameClippedByDisplayCutout;
}
private ClientWindowFrames(Parcel in) {
- frame = Rect.CREATOR.createFromParcel(in);
- displayFrame = Rect.CREATOR.createFromParcel(in);
- backdropFrame = Rect.CREATOR.createFromParcel(in);
+ readFromParcel(in);
}
/** Needed for AIDL out parameters. */
public void readFromParcel(Parcel in) {
frame.readFromParcel(in);
displayFrame.readFromParcel(in);
+ parentFrame.readFromParcel(in);
backdropFrame.readFromParcel(in);
+ isParentFrameClippedByDisplayCutout = in.readBoolean();
}
@Override
public void writeToParcel(Parcel dest, int flags) {
frame.writeToParcel(dest, flags);
displayFrame.writeToParcel(dest, flags);
+ parentFrame.writeToParcel(dest, flags);
backdropFrame.writeToParcel(dest, flags);
+ dest.writeBoolean(isParentFrameClippedByDisplayCutout);
}
@Override
@@ -75,7 +83,9 @@
final StringBuilder sb = new StringBuilder(32);
return "ClientWindowFrames{frame=" + frame.toShortString(sb)
+ " display=" + displayFrame.toShortString(sb)
- + " backdrop=" + backdropFrame.toShortString(sb) + "}";
+ + " parentFrame=" + parentFrame.toShortString(sb)
+ + " backdrop=" + backdropFrame.toShortString(sb)
+ + " parentClippedByDisplayCutout=" + isParentFrameClippedByDisplayCutout + "}";
}
@Override
diff --git a/core/java/android/window/OnBackInvokedCallback.java b/core/java/android/window/OnBackInvokedCallback.java
index dcd80fd..400a56f 100644
--- a/core/java/android/window/OnBackInvokedCallback.java
+++ b/core/java/android/window/OnBackInvokedCallback.java
@@ -33,7 +33,7 @@
* within the same priority. Between different pirorities, callbacks with higher priority
* are invoked first.
*
- * See {@link OnBackInvokedDispatcher#registerOnBackInvokedCallback(OnBackInvokedCallback, int)}
+ * See {@link OnBackInvokedDispatcher#registerOnBackInvokedCallback(int, OnBackInvokedCallback)}
* for specifying callback priority.
*/
public interface OnBackInvokedCallback {
diff --git a/core/java/android/window/OnBackInvokedDispatcher.java b/core/java/android/window/OnBackInvokedDispatcher.java
index 63e6d30..5eed8cd 100644
--- a/core/java/android/window/OnBackInvokedDispatcher.java
+++ b/core/java/android/window/OnBackInvokedDispatcher.java
@@ -94,15 +94,15 @@
* Within the same priority level, callbacks are invoked in the reverse order in which
* they are registered. Higher priority callbacks are invoked before lower priority ones.
*
+ * @param priority The priority of the callback.
* @param callback The callback to be registered. If the callback instance has been already
* registered, the existing instance (no matter its priority) will be
* unregistered and registered again.
- * @param priority The priority of the callback.
* @throws {@link IllegalArgumentException} if the priority is negative.
*/
- @SuppressLint({"SamShouldBeLast", "ExecutorRegistration"})
+ @SuppressLint({"ExecutorRegistration"})
void registerOnBackInvokedCallback(
- @NonNull OnBackInvokedCallback callback, @Priority @IntRange(from = 0) int priority);
+ @Priority @IntRange(from = 0) int priority, @NonNull OnBackInvokedCallback callback);
/**
* Unregisters a {@link OnBackInvokedCallback}.
diff --git a/core/java/android/window/ProxyOnBackInvokedDispatcher.java b/core/java/android/window/ProxyOnBackInvokedDispatcher.java
index cf17a21..2b2f5e9 100644
--- a/core/java/android/window/ProxyOnBackInvokedDispatcher.java
+++ b/core/java/android/window/ProxyOnBackInvokedDispatcher.java
@@ -44,7 +44,7 @@
/**
* List of pair representing an {@link OnBackInvokedCallback} and its associated priority.
*
- * @see OnBackInvokedDispatcher#registerOnBackInvokedCallback(OnBackInvokedCallback, int)
+ * @see OnBackInvokedDispatcher#registerOnBackInvokedCallback(int, OnBackInvokedCallback)
*/
private final List<Pair<OnBackInvokedCallback, Integer>> mCallbacks = new ArrayList<>();
private final Object mLock = new Object();
@@ -52,7 +52,7 @@
@Override
public void registerOnBackInvokedCallback(
- @NonNull OnBackInvokedCallback callback, int priority) {
+ int priority, @NonNull OnBackInvokedCallback callback) {
if (DEBUG) {
Log.v(TAG, String.format("Pending register %s. Actual=%s", callback,
mActualDispatcherOwner));
@@ -91,7 +91,7 @@
mCallbacks.add(Pair.create(callback, priority));
if (mActualDispatcherOwner != null) {
mActualDispatcherOwner.getOnBackInvokedDispatcher().registerOnBackInvokedCallback(
- callback, priority);
+ priority, callback);
}
}
}
@@ -115,7 +115,7 @@
for (Pair<OnBackInvokedCallback, Integer> callbackPair : mCallbacks) {
int priority = callbackPair.second;
if (priority >= 0) {
- dispatcher.registerOnBackInvokedCallback(callbackPair.first, priority);
+ dispatcher.registerOnBackInvokedCallback(priority, callbackPair.first);
} else {
dispatcher.registerSystemOnBackInvokedCallback(callbackPair.first);
}
diff --git a/core/java/android/window/WindowInfosListener.java b/core/java/android/window/WindowInfosListener.java
index 9d4545c..8db5a5e 100644
--- a/core/java/android/window/WindowInfosListener.java
+++ b/core/java/android/window/WindowInfosListener.java
@@ -17,6 +17,7 @@
package android.window;
import android.graphics.Matrix;
+import android.util.Pair;
import android.util.Size;
import android.view.InputWindowHandle;
@@ -47,9 +48,13 @@
/**
* Register the WindowInfosListener.
+ *
+ * @return The cached values for InputWindowHandles and DisplayInfos. This is the last updated
+ * value that was sent from SurfaceFlinger to this particular process. If there was nothing
+ * registered previously, then the data can be empty.
*/
- public void register() {
- nativeRegister(mNativeListener);
+ public Pair<InputWindowHandle[], DisplayInfo[]> register() {
+ return nativeRegister(mNativeListener);
}
/**
@@ -60,7 +65,7 @@
}
private static native long nativeCreate(WindowInfosListener thiz);
- private static native void nativeRegister(long ptr);
+ private static native Pair<InputWindowHandle[], DisplayInfo[]> nativeRegister(long ptr);
private static native void nativeUnregister(long ptr);
private static native long nativeGetFinalizer();
diff --git a/core/java/android/window/WindowOnBackInvokedDispatcher.java b/core/java/android/window/WindowOnBackInvokedDispatcher.java
index 5dbb551..97573c2 100644
--- a/core/java/android/window/WindowOnBackInvokedDispatcher.java
+++ b/core/java/android/window/WindowOnBackInvokedDispatcher.java
@@ -53,7 +53,7 @@
private static final String TAG = "WindowOnBackDispatcher";
private static final String BACK_PREDICTABILITY_PROP = "persist.debug.back_predictability";
private static final boolean IS_BACK_PREDICTABILITY_ENABLED = SystemProperties
- .getInt(BACK_PREDICTABILITY_PROP, 0) > 0;
+ .getInt(BACK_PREDICTABILITY_PROP, 1) > 0;
/** Convenience hashmap to quickly decide if a callback has been added. */
private final HashMap<OnBackInvokedCallback, Integer> mAllCallbacks = new HashMap<>();
@@ -83,7 +83,7 @@
// TODO: Take an Executor for the callback to run on.
@Override
public void registerOnBackInvokedCallback(
- @NonNull OnBackInvokedCallback callback, @Priority int priority) {
+ @Priority int priority, @NonNull OnBackInvokedCallback callback) {
if (priority < 0) {
throw new IllegalArgumentException("Application registered OnBackInvokedCallback "
+ "cannot have negative priority. Priority: " + priority);
diff --git a/core/java/com/android/internal/app/ChooserMultiProfilePagerAdapter.java b/core/java/com/android/internal/app/ChooserMultiProfilePagerAdapter.java
index 393bff4..9164089 100644
--- a/core/java/com/android/internal/app/ChooserMultiProfilePagerAdapter.java
+++ b/core/java/com/android/internal/app/ChooserMultiProfilePagerAdapter.java
@@ -247,54 +247,54 @@
}
private String getWorkAppPausedTitle() {
- return getContext().getSystemService(DevicePolicyManager.class).getString(
+ return getContext().getSystemService(DevicePolicyManager.class).getResources().getString(
RESOLVER_WORK_PAUSED_TITLE,
() -> getContext().getString(R.string.resolver_turn_on_work_apps));
}
private String getCrossProfileBlockedTitle() {
- return getContext().getSystemService(DevicePolicyManager.class).getString(
+ return getContext().getSystemService(DevicePolicyManager.class).getResources().getString(
RESOLVER_CROSS_PROFILE_BLOCKED_TITLE,
() -> getContext().getString(R.string.resolver_cross_profile_blocked));
}
private String getCantShareWithWorkMessage() {
- return getContext().getSystemService(DevicePolicyManager.class).getString(
+ return getContext().getSystemService(DevicePolicyManager.class).getResources().getString(
RESOLVER_CANT_SHARE_WITH_WORK,
() -> getContext().getString(
R.string.resolver_cant_share_with_work_apps_explanation));
}
private String getCantShareWithPersonalMessage() {
- return getContext().getSystemService(DevicePolicyManager.class).getString(
+ return getContext().getSystemService(DevicePolicyManager.class).getResources().getString(
RESOLVER_CANT_SHARE_WITH_PERSONAL,
() -> getContext().getString(
R.string.resolver_cant_share_with_personal_apps_explanation));
}
private String getCantAccessWorkMessage() {
- return getContext().getSystemService(DevicePolicyManager.class).getString(
+ return getContext().getSystemService(DevicePolicyManager.class).getResources().getString(
RESOLVER_CANT_ACCESS_WORK,
() -> getContext().getString(
R.string.resolver_cant_access_work_apps_explanation));
}
private String getCantAccessPersonalMessage() {
- return getContext().getSystemService(DevicePolicyManager.class).getString(
+ return getContext().getSystemService(DevicePolicyManager.class).getResources().getString(
RESOLVER_CANT_ACCESS_PERSONAL,
() -> getContext().getString(
R.string.resolver_cant_access_personal_apps_explanation));
}
private String getNoWorkAppsAvailableMessage() {
- return getContext().getSystemService(DevicePolicyManager.class).getString(
+ return getContext().getSystemService(DevicePolicyManager.class).getResources().getString(
RESOLVER_NO_WORK_APPS,
() -> getContext().getString(
R.string.resolver_no_work_apps_available));
}
private String getNoPersonalAppsAvailableMessage() {
- return getContext().getSystemService(DevicePolicyManager.class).getString(
+ return getContext().getSystemService(DevicePolicyManager.class).getResources().getString(
RESOLVER_NO_PERSONAL_APPS,
() -> getContext().getString(
R.string.resolver_no_personal_apps_available));
diff --git a/core/java/com/android/internal/app/IntentForwarderActivity.java b/core/java/com/android/internal/app/IntentForwarderActivity.java
index 25b8dba..6e76906 100644
--- a/core/java/com/android/internal/app/IntentForwarderActivity.java
+++ b/core/java/com/android/internal/app/IntentForwarderActivity.java
@@ -163,13 +163,13 @@
}
private String getForwardToPersonalMessage() {
- return getSystemService(DevicePolicyManager.class).getString(
+ return getSystemService(DevicePolicyManager.class).getResources().getString(
FORWARD_INTENT_TO_PERSONAL,
() -> getString(com.android.internal.R.string.forward_intent_to_owner));
}
private String getForwardToWorkMessage() {
- return getSystemService(DevicePolicyManager.class).getString(
+ return getSystemService(DevicePolicyManager.class).getResources().getString(
FORWARD_INTENT_TO_WORK,
() -> getString(com.android.internal.R.string.forward_intent_to_work));
}
diff --git a/core/java/com/android/internal/app/ResolverActivity.java b/core/java/com/android/internal/app/ResolverActivity.java
index fd5eac8..5ebb148 100644
--- a/core/java/com/android/internal/app/ResolverActivity.java
+++ b/core/java/com/android/internal/app/ResolverActivity.java
@@ -850,13 +850,13 @@
}
private String getForwardToPersonalMsg() {
- return getSystemService(DevicePolicyManager.class).getString(
+ return getSystemService(DevicePolicyManager.class).getResources().getString(
FORWARD_INTENT_TO_PERSONAL,
() -> getString(com.android.internal.R.string.forward_intent_to_owner));
}
private String getForwardToWorkMsg() {
- return getSystemService(DevicePolicyManager.class).getString(
+ return getSystemService(DevicePolicyManager.class).getResources().getString(
FORWARD_INTENT_TO_WORK,
() -> getString(com.android.internal.R.string.forward_intent_to_work));
}
@@ -1150,7 +1150,7 @@
}
private String getWorkProfileNotSupportedMsg(String launcherName) {
- return getSystemService(DevicePolicyManager.class).getString(
+ return getSystemService(DevicePolicyManager.class).getResources().getString(
RESOLVER_WORK_PROFILE_NOT_SUPPORTED,
() -> getString(
com.android.internal.R.string.activity_resolver_work_profiles_support,
@@ -1879,12 +1879,12 @@
}
private String getPersonalTabLabel() {
- return getSystemService(DevicePolicyManager.class).getString(
+ return getSystemService(DevicePolicyManager.class).getResources().getString(
RESOLVER_PERSONAL_TAB, () -> getString(R.string.resolver_personal_tab));
}
private String getWorkTabLabel() {
- return getSystemService(DevicePolicyManager.class).getString(
+ return getSystemService(DevicePolicyManager.class).getResources().getString(
RESOLVER_WORK_TAB, () -> getString(R.string.resolver_work_tab));
}
@@ -1935,13 +1935,13 @@
}
private String getPersonalTabAccessibilityLabel() {
- return getSystemService(DevicePolicyManager.class).getString(
+ return getSystemService(DevicePolicyManager.class).getResources().getString(
RESOLVER_PERSONAL_TAB_ACCESSIBILITY,
() -> getString(R.string.resolver_personal_tab_accessibility));
}
private String getWorkTabAccessibilityLabel() {
- return getSystemService(DevicePolicyManager.class).getString(
+ return getSystemService(DevicePolicyManager.class).getResources().getString(
RESOLVER_WORK_TAB_ACCESSIBILITY,
() -> getString(R.string.resolver_work_tab_accessibility));
}
diff --git a/core/java/com/android/internal/app/ResolverMultiProfilePagerAdapter.java b/core/java/com/android/internal/app/ResolverMultiProfilePagerAdapter.java
index 4da59a3..f4e568b 100644
--- a/core/java/com/android/internal/app/ResolverMultiProfilePagerAdapter.java
+++ b/core/java/com/android/internal/app/ResolverMultiProfilePagerAdapter.java
@@ -242,40 +242,40 @@
}
private String getWorkAppPausedTitle() {
- return getContext().getSystemService(DevicePolicyManager.class).getString(
+ return getContext().getSystemService(DevicePolicyManager.class).getResources().getString(
RESOLVER_WORK_PAUSED_TITLE,
() -> getContext().getString(R.string.resolver_turn_on_work_apps));
}
private String getCrossProfileBlockedTitle() {
- return getContext().getSystemService(DevicePolicyManager.class).getString(
+ return getContext().getSystemService(DevicePolicyManager.class).getResources().getString(
RESOLVER_CROSS_PROFILE_BLOCKED_TITLE,
() -> getContext().getString(R.string.resolver_cross_profile_blocked));
}
private String getCantAccessWorkMessage() {
- return getContext().getSystemService(DevicePolicyManager.class).getString(
+ return getContext().getSystemService(DevicePolicyManager.class).getResources().getString(
RESOLVER_CANT_ACCESS_WORK,
() -> getContext().getString(
R.string.resolver_cant_access_work_apps_explanation));
}
private String getCantAccessPersonalMessage() {
- return getContext().getSystemService(DevicePolicyManager.class).getString(
+ return getContext().getSystemService(DevicePolicyManager.class).getResources().getString(
RESOLVER_CANT_ACCESS_PERSONAL,
() -> getContext().getString(
R.string.resolver_cant_access_personal_apps_explanation));
}
private String getNoWorkAppsAvailableMessage() {
- return getContext().getSystemService(DevicePolicyManager.class).getString(
+ return getContext().getSystemService(DevicePolicyManager.class).getResources().getString(
RESOLVER_NO_WORK_APPS,
() -> getContext().getString(
R.string.resolver_no_work_apps_available));
}
private String getNoPersonalAppsAvailableMessage() {
- return getContext().getSystemService(DevicePolicyManager.class).getString(
+ return getContext().getSystemService(DevicePolicyManager.class).getResources().getString(
RESOLVER_NO_PERSONAL_APPS,
() -> getContext().getString(
R.string.resolver_no_personal_apps_available));
diff --git a/core/java/com/android/internal/app/UnlaunchableAppActivity.java b/core/java/com/android/internal/app/UnlaunchableAppActivity.java
index 3531fad..957a636 100644
--- a/core/java/com/android/internal/app/UnlaunchableAppActivity.java
+++ b/core/java/com/android/internal/app/UnlaunchableAppActivity.java
@@ -95,12 +95,12 @@
}
private String getDialogTitle() {
- return getSystemService(DevicePolicyManager.class).getString(
+ return getSystemService(DevicePolicyManager.class).getResources().getString(
UNLAUNCHABLE_APP_WORK_PAUSED_TITLE, () -> getString(R.string.work_mode_off_title));
}
private String getDialogMessage() {
- return getSystemService(DevicePolicyManager.class).getString(
+ return getSystemService(DevicePolicyManager.class).getResources().getString(
UNLAUNCHABLE_APP_WORK_PAUSED_MESSAGE,
() -> getString(R.string.work_mode_off_message));
}
diff --git a/core/java/com/android/internal/infra/ServiceConnector.java b/core/java/com/android/internal/infra/ServiceConnector.java
index 9e07f97..cb16267 100644
--- a/core/java/com/android/internal/infra/ServiceConnector.java
+++ b/core/java/com/android/internal/infra/ServiceConnector.java
@@ -31,6 +31,7 @@
import android.os.RemoteException;
import android.os.UserHandle;
import android.util.Log;
+import android.util.Slog;
import java.io.PrintWriter;
import java.util.ArrayDeque;
@@ -562,10 +563,21 @@
void unbindJobThread() {
cancelTimeout();
I service = mService;
+ // TODO(b/224695239): This is actually checking wasConnected. Rename and/or fix
+ // implementation based on what this should actually be checking. At least the first
+ // check for calling unbind is the correct behavior, though.
boolean wasBound = service != null;
+ if (wasBound || mBinding) {
+ try {
+ mContext.unbindService(mServiceConnection);
+ } catch (IllegalArgumentException e) { // TODO(b/224697137): Fix the race condition
+ // that requires catching this (crashes if
+ // service isn't currently bound).
+ Slog.e(LOG_TAG, "Failed to unbind: " + e);
+ }
+ }
if (wasBound) {
dispatchOnServiceConnectionStatusChanged(service, false);
- mContext.unbindService(mServiceConnection);
service.asBinder().unlinkToDeath(this, 0);
mService = null;
}
diff --git a/core/java/com/android/internal/jank/FrameTracker.java b/core/java/com/android/internal/jank/FrameTracker.java
index 34c47ed..06bc4b5 100644
--- a/core/java/com/android/internal/jank/FrameTracker.java
+++ b/core/java/com/android/internal/jank/FrameTracker.java
@@ -33,6 +33,7 @@
import android.graphics.HardwareRendererObserver;
import android.os.Handler;
import android.os.Trace;
+import android.text.TextUtils;
import android.util.Log;
import android.util.SparseArray;
import android.view.Choreographer;
@@ -188,6 +189,7 @@
if (mBeginVsyncId != INVALID_ID) {
mSurfaceControlWrapper.addJankStatsListener(
FrameTracker.this, mSurfaceControl);
+ markEvent("FT#deferMonitoring");
postTraceStartMarker();
}
}
@@ -241,8 +243,9 @@
}
if (mSurfaceControl != null) {
if (mDeferMonitoring) {
+ markEvent("FT#deferMonitoring");
// Normal case, we begin the instrument from the very beginning,
- // except the first frame.
+ // will exclude the first frame.
postTraceStartMarker();
} else {
// If we don't begin the instrument from the very beginning,
@@ -272,6 +275,7 @@
return;
}
mTracingStarted = true;
+ markEvent("FT#begin");
Trace.beginAsyncSection(mSession.getName(), (int) mBeginVsyncId);
}
}
@@ -295,6 +299,7 @@
Log.d(TAG, "end: " + mSession.getName()
+ ", end=" + mEndVsyncId + ", reason=" + reason);
}
+ markEvent("FT#end#" + reason);
Trace.endAsyncSection(mSession.getName(), (int) mBeginVsyncId);
mSession.setReason(reason);
@@ -322,6 +327,7 @@
reason == REASON_CANCEL_NOT_BEGUN || reason == REASON_CANCEL_SAME_VSYNC;
if (mCancelled || (mEndVsyncId != INVALID_ID && !cancelFromEnd)) return false;
mCancelled = true;
+ markEvent("FT#cancel#" + reason);
// We don't need to end the trace section if it never begun.
if (mTracingStarted) {
Trace.endAsyncSection(mSession.getName(), (int) mBeginVsyncId);
@@ -343,6 +349,11 @@
}
}
+ private void markEvent(String desc) {
+ Trace.beginSection(TextUtils.formatSimple("%s#%s", mSession.getName(), desc));
+ Trace.endSection();
+ }
+
private void notifyCujEvent(String action) {
if (mListener == null) return;
mListener.onCujEvents(mSession, action);
diff --git a/core/java/com/android/internal/logging/InstanceId.java b/core/java/com/android/internal/logging/InstanceId.java
deleted file mode 100644
index c90d8512..0000000
--- a/core/java/com/android/internal/logging/InstanceId.java
+++ /dev/null
@@ -1,98 +0,0 @@
-/*
- * Copyright (C) 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.internal.logging;
-
-import static java.lang.Math.max;
-import static java.lang.Math.min;
-
-import android.annotation.Nullable;
-import android.os.Parcel;
-import android.os.Parcelable;
-
-import com.android.internal.annotations.VisibleForTesting;
-
-/**
- * An opaque identifier used to disambiguate which logs refer to a particular instance of some
- * UI element. Useful when there might be multiple instances simultaneously active.
- * Obtain from InstanceIdSequence. Clipped to range [0, INSTANCE_ID_MAX].
- */
-public final class InstanceId implements Parcelable {
- // At most 20 bits: ~1m possibilities, ~0.5% probability of collision in 100 values
- static final int INSTANCE_ID_MAX = 1 << 20;
-
- private final int mId;
- InstanceId(int id) {
- mId = min(max(0, id), INSTANCE_ID_MAX);
- }
-
- private InstanceId(Parcel in) {
- this(in.readInt());
- }
-
- @VisibleForTesting
- public int getId() {
- return mId;
- }
-
- /**
- * Create a fake instance ID for testing purposes. Not for production use. See also
- * InstanceIdSequenceFake, which is a testing replacement for InstanceIdSequence.
- * @param id The ID you want to assign.
- * @return new InstanceId.
- */
- @VisibleForTesting
- public static InstanceId fakeInstanceId(int id) {
- return new InstanceId(id);
- }
-
- @Override
- public int hashCode() {
- return mId;
- }
-
- @Override
- public boolean equals(@Nullable Object obj) {
- if (!(obj instanceof InstanceId)) {
- return false;
- }
- return mId == ((InstanceId) obj).mId;
- }
-
- @Override
- public int describeContents() {
- return 0;
- }
-
- @Override
- public void writeToParcel(Parcel out, int flags) {
- out.writeInt(mId);
- }
-
- public static final Parcelable.Creator<InstanceId> CREATOR =
- new Parcelable.Creator<InstanceId>() {
- @Override
- public InstanceId createFromParcel(Parcel in) {
- return new InstanceId(in);
- }
-
- @Override
- public InstanceId[] newArray(int size) {
- return new InstanceId[size];
- }
- };
-
-}
diff --git a/core/java/com/android/internal/logging/InstanceIdSequence.java b/core/java/com/android/internal/logging/InstanceIdSequence.java
deleted file mode 100644
index 3464310..0000000
--- a/core/java/com/android/internal/logging/InstanceIdSequence.java
+++ /dev/null
@@ -1,62 +0,0 @@
-/*
- * Copyright (C) 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.internal.logging;
-
-import static java.lang.Math.max;
-import static java.lang.Math.min;
-
-import com.android.internal.annotations.VisibleForTesting;
-
-import java.security.SecureRandom;
-import java.util.Random;
-
-/**
- * Generates random InstanceIds in range [1, instanceIdMax] for passing to
- * UiEventLogger.logWithInstanceId(). Holds a SecureRandom, which self-seeds on
- * first use; try to give it a long lifetime. Safe for concurrent use.
- */
-public class InstanceIdSequence {
- protected final int mInstanceIdMax;
- private final Random mRandom = new SecureRandom();
-
- /**
- * Constructs a sequence with identifiers [1, instanceIdMax]. Capped at INSTANCE_ID_MAX.
- * @param instanceIdMax Limiting value of identifiers. Normally positive: otherwise you get
- * an all-1 sequence.
- */
- public InstanceIdSequence(int instanceIdMax) {
- mInstanceIdMax = min(max(1, instanceIdMax), InstanceId.INSTANCE_ID_MAX);
- }
-
- /**
- * Gets the next instance from the sequence. Safe for concurrent use.
- * @return new InstanceId
- */
- public InstanceId newInstanceId() {
- return newInstanceIdInternal(1 + mRandom.nextInt(mInstanceIdMax));
- }
-
- /**
- * Factory function for instance IDs, used for testing.
- * @param id
- * @return new InstanceId(id)
- */
- @VisibleForTesting
- protected InstanceId newInstanceIdInternal(int id) {
- return new InstanceId(id);
- }
-}
diff --git a/core/java/com/android/internal/logging/UiEvent.java b/core/java/com/android/internal/logging/UiEvent.java
deleted file mode 100644
index 0407b07..0000000
--- a/core/java/com/android/internal/logging/UiEvent.java
+++ /dev/null
@@ -1,30 +0,0 @@
-/*
- * Copyright (C) 2019 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.internal.logging;
-
-import static java.lang.annotation.ElementType.FIELD;
-import static java.lang.annotation.RetentionPolicy.SOURCE;
-
-import java.lang.annotation.Retention;
-import java.lang.annotation.Target;
-
-@Retention(SOURCE)
-@Target(FIELD)
-public @interface UiEvent {
- /** An explanation, suitable for Android analysts, of the UI event that this log represents. */
- String doc();
-}
diff --git a/core/java/com/android/internal/logging/UiEventLogger.java b/core/java/com/android/internal/logging/UiEventLogger.java
deleted file mode 100644
index 5378b03..0000000
--- a/core/java/com/android/internal/logging/UiEventLogger.java
+++ /dev/null
@@ -1,111 +0,0 @@
-/*
- * Copyright (C) 2019 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.internal.logging;
-
-import android.annotation.NonNull;
-import android.annotation.Nullable;
-
-/**
- * Logging interface for UI events. Normal implementation is UiEventLoggerImpl.
- * For testing, use fake implementation UiEventLoggerFake.
- *
- * See go/sysui-event-logs and UiEventReported atom in atoms.proto.
- */
-public interface UiEventLogger {
- /** Put your Event IDs in enums that implement this interface, and document them using the
- * UiEventEnum annotation.
- * Event IDs must be globally unique. This will be enforced by tooling (forthcoming).
- * OEMs should use event IDs above 100000 and below 1000000 (1 million).
- */
- interface UiEventEnum {
-
- /**
- * Tag used to request new UI Event IDs via presubmit analysis.
- *
- * <p>Use RESERVE_NEW_UI_EVENT_ID as the constructor parameter for a new {@link EventEnum}
- * to signal the presubmit analyzer to reserve a new ID for the event. The new ID will be
- * returned as a Gerrit presubmit finding. Do not submit {@code RESERVE_NEW_UI_EVENT_ID} as
- * the constructor parameter for any event.
- *
- * <pre>
- * @UiEvent(doc = "Briefly describe the interaction when this event will be logged")
- * UNIQUE_EVENT_NAME(RESERVE_NEW_UI_EVENT_ID);
- * </pre>
- */
- int RESERVE_NEW_UI_EVENT_ID = Integer.MIN_VALUE; // Negative IDs are ignored by the logger.
-
- int getId();
- }
-
- /**
- * Log a simple event, with no package information. Does nothing if event.getId() <= 0.
- * @param event an enum implementing UiEventEnum interface.
- */
- void log(@NonNull UiEventEnum event);
-
- /**
- * Log a simple event with an instance id, without package information.
- * Does nothing if event.getId() <= 0.
- * @param event an enum implementing UiEventEnum interface.
- * @param instance An identifier obtained from an InstanceIdSequence. If null, reduces to log().
- */
- void log(@NonNull UiEventEnum event, @Nullable InstanceId instance);
-
- /**
- * Log an event with package information. Does nothing if event.getId() <= 0.
- * Give both uid and packageName if both are known, but one may be omitted if unknown.
- * @param event an enum implementing UiEventEnum interface.
- * @param uid the uid of the relevant app, if known (0 otherwise).
- * @param packageName the package name of the relevant app, if known (null otherwise).
- */
- void log(@NonNull UiEventEnum event, int uid, @Nullable String packageName);
-
- /**
- * Log an event with package information and an instance ID.
- * Does nothing if event.getId() <= 0.
- * @param event an enum implementing UiEventEnum interface.
- * @param uid the uid of the relevant app, if known (0 otherwise).
- * @param packageName the package name of the relevant app, if known (null otherwise).
- * @param instance An identifier obtained from an InstanceIdSequence. If null, reduces to log().
- */
- void logWithInstanceId(@NonNull UiEventEnum event, int uid, @Nullable String packageName,
- @Nullable InstanceId instance);
-
- /**
- * Log an event with ranked-choice information along with package.
- * Does nothing if event.getId() <= 0.
- * @param event an enum implementing UiEventEnum interface.
- * @param uid the uid of the relevant app, if known (0 otherwise).
- * @param packageName the package name of the relevant app, if known (null otherwise).
- * @param position the position picked.
- */
- void logWithPosition(@NonNull UiEventEnum event, int uid, @Nullable String packageName,
- int position);
-
- /**
- * Log an event with ranked-choice information along with package and instance ID.
- * Does nothing if event.getId() <= 0.
- * @param event an enum implementing UiEventEnum interface.
- * @param uid the uid of the relevant app, if known (0 otherwise).
- * @param packageName the package name of the relevant app, if known (null otherwise).
- * @param instance An identifier obtained from an InstanceIdSequence. If null, reduces to
- * logWithPosition().
- * @param position the position picked.
- */
- void logWithInstanceIdAndPosition(@NonNull UiEventEnum event, int uid,
- @Nullable String packageName, @Nullable InstanceId instance, int position);
-}
diff --git a/core/java/com/android/internal/notification/SystemNotificationChannels.java b/core/java/com/android/internal/notification/SystemNotificationChannels.java
index b79c0be..a93c487 100644
--- a/core/java/com/android/internal/notification/SystemNotificationChannels.java
+++ b/core/java/com/android/internal/notification/SystemNotificationChannels.java
@@ -221,7 +221,7 @@
private static String getDeviceAdminNotificationChannelName(Context context) {
DevicePolicyManager dpm = context.getSystemService(DevicePolicyManager.class);
- return dpm.getString(NOTIFICATION_CHANNEL_DEVICE_ADMIN,
+ return dpm.getResources().getString(NOTIFICATION_CHANNEL_DEVICE_ADMIN,
() -> context.getString(R.string.notification_channel_device_admin));
}
diff --git a/core/java/com/android/internal/os/BatteryStatsImpl.java b/core/java/com/android/internal/os/BatteryStatsImpl.java
index 5253956..8901c07 100644
--- a/core/java/com/android/internal/os/BatteryStatsImpl.java
+++ b/core/java/com/android/internal/os/BatteryStatsImpl.java
@@ -166,7 +166,7 @@
private static final int MAGIC = 0xBA757475; // 'BATSTATS'
// Current on-disk Parcel version
- static final int VERSION = 206;
+ static final int VERSION = 207;
// The maximum number of names wakelocks we will keep track of
// per uid; once the limit is reached, we batch the remaining wakelocks
@@ -964,6 +964,16 @@
* Timers for each combination of frequency range and signal strength.
*/
public final StopwatchTimer[][] perStateTimers;
+ /**
+ * Counters tracking the time (in milliseconds) spent transmitting data in a given state.
+ */
+ @Nullable
+ private LongSamplingCounter[][] mPerStateTxDurationMs = null;
+ /**
+ * Counters tracking the time (in milliseconds) spent receiving data in at given frequency.
+ */
+ @Nullable
+ private LongSamplingCounter[] mPerFrequencyRxDurationMs = null;
RadioAccessTechnologyBatteryStats(int freqCount, Clock clock, TimeBase timeBase) {
perStateTimers =
@@ -1024,15 +1034,198 @@
}
/**
- * Reset display timers.
+ * Returns the duration in milliseconds spent in a given state since the last mark.
+ */
+ public long getTimeSinceMark(@ServiceState.FrequencyRange int frequencyRange,
+ int signalStrength, long elapsedRealtimeMs) {
+ return perStateTimers[frequencyRange][signalStrength].getTimeSinceMarkLocked(
+ elapsedRealtimeMs * 1000) / 1000;
+ }
+
+ /**
+ * Set mark for all timers.
+ */
+ public void setMark(long elapsedRealtimeMs) {
+ final int size = perStateTimers.length;
+ for (int i = 0; i < size; i++) {
+ for (int j = 0; j < CellSignalStrength.NUM_SIGNAL_STRENGTH_BINS; j++) {
+ perStateTimers[i][j].setMark(elapsedRealtimeMs);
+ }
+ }
+ }
+
+ /**
+ * Returns numbers of frequencies tracked for this RAT.
+ */
+ public int getFrequencyRangeCount() {
+ return perStateTimers.length;
+ }
+
+ /**
+ * Add TX time for a given state.
+ */
+ public void incrementTxDuration(@ServiceState.FrequencyRange int frequencyRange,
+ int signalStrength, long durationMs) {
+ getTxDurationCounter(frequencyRange, signalStrength, true).addCountLocked(durationMs);
+ }
+
+ /**
+ * Add TX time for a given frequency.
+ */
+ public void incrementRxDuration(@ServiceState.FrequencyRange int frequencyRange,
+ long durationMs) {
+ getRxDurationCounter(frequencyRange, true).addCountLocked(durationMs);
+ }
+
+ /**
+ * Reset radio access technology timers and counts.
*/
public void reset(long elapsedRealtimeUs) {
final int size = perStateTimers.length;
for (int i = 0; i < size; i++) {
for (int j = 0; j < CellSignalStrength.NUM_SIGNAL_STRENGTH_BINS; j++) {
perStateTimers[i][j].reset(false, elapsedRealtimeUs);
+ if (mPerStateTxDurationMs == null) continue;
+ mPerStateTxDurationMs[i][j].reset(false, elapsedRealtimeUs);
+ }
+ if (mPerFrequencyRxDurationMs == null) continue;
+ mPerFrequencyRxDurationMs[i].reset(false, elapsedRealtimeUs);
+ }
+ }
+
+ /**
+ * Write data to summary parcel
+ */
+ public void writeSummaryToParcel(Parcel out, long elapsedRealtimeUs) {
+ final int freqCount = perStateTimers.length;
+ out.writeInt(freqCount);
+ out.writeInt(CellSignalStrength.NUM_SIGNAL_STRENGTH_BINS);
+ for (int i = 0; i < freqCount; i++) {
+ for (int j = 0; j < CellSignalStrength.NUM_SIGNAL_STRENGTH_BINS; j++) {
+ perStateTimers[i][j].writeSummaryFromParcelLocked(out, elapsedRealtimeUs);
}
}
+
+ if (mPerStateTxDurationMs == null) {
+ out.writeInt(0);
+ } else {
+ out.writeInt(1);
+ for (int i = 0; i < freqCount; i++) {
+ for (int j = 0; j < CellSignalStrength.NUM_SIGNAL_STRENGTH_BINS; j++) {
+ mPerStateTxDurationMs[i][j].writeSummaryFromParcelLocked(out);
+ }
+ }
+ }
+
+ if (mPerFrequencyRxDurationMs == null) {
+ out.writeInt(0);
+ } else {
+ out.writeInt(1);
+ for (int i = 0; i < freqCount; i++) {
+ mPerFrequencyRxDurationMs[i].writeSummaryFromParcelLocked(out);
+ }
+ }
+ }
+
+ /**
+ * Read data from summary parcel
+ */
+ public void readSummaryFromParcel(Parcel in) {
+ final int oldFreqCount = in.readInt();
+ final int oldSignalStrengthCount = in.readInt();
+ final int currFreqCount = perStateTimers.length;
+ final int currSignalStrengthCount = CellSignalStrength.NUM_SIGNAL_STRENGTH_BINS;
+
+ for (int freq = 0; freq < oldFreqCount; freq++) {
+ for (int strength = 0; strength < oldSignalStrengthCount; strength++) {
+ if (freq >= currFreqCount || strength >= currSignalStrengthCount) {
+ // Mismatch with the summary parcel. Consume the data but don't use it.
+ final StopwatchTimer temp = new StopwatchTimer(null, null, -1, null,
+ new TimeBase());
+ // Consume perStateTimers data.
+ temp.readSummaryFromParcelLocked(in);
+ } else {
+ perStateTimers[freq][strength].readSummaryFromParcelLocked(in);
+ }
+ }
+ }
+
+ if (in.readInt() == 1) {
+ for (int freq = 0; freq < oldFreqCount; freq++) {
+ for (int strength = 0; strength < oldSignalStrengthCount; strength++) {
+ if (freq >= currFreqCount || strength >= currSignalStrengthCount) {
+ // Mismatch with the summary parcel. Consume the data but don't use it.
+ final StopwatchTimer temp = new StopwatchTimer(null, null, -1, null,
+ new TimeBase());
+ // Consume mPerStateTxDurationMs data.
+ temp.readSummaryFromParcelLocked(in);
+ }
+ getTxDurationCounter(freq, strength, true).readSummaryFromParcelLocked(in);
+ }
+ }
+ }
+
+ if (in.readInt() == 1) {
+ for (int freq = 0; freq < oldFreqCount; freq++) {
+ if (freq >= currFreqCount) {
+ // Mismatch with the summary parcel. Consume the data but don't use it.
+ final StopwatchTimer
+ temp = new StopwatchTimer(null, null, -1, null, new TimeBase());
+ // Consume mPerFrequencyRxDurationMs data.
+ temp.readSummaryFromParcelLocked(in);
+ continue;
+ }
+ getRxDurationCounter(freq, true).readSummaryFromParcelLocked(in);
+ }
+ }
+ }
+
+ private LongSamplingCounter getTxDurationCounter(
+ @ServiceState.FrequencyRange int frequencyRange, int signalStrength, boolean make) {
+ if (mPerStateTxDurationMs == null) {
+ if (!make) return null;
+
+ final int freqCount = getFrequencyRangeCount();
+ final int signalStrengthCount = perStateTimers[0].length;
+ final TimeBase timeBase = perStateTimers[0][0].mTimeBase;
+ mPerStateTxDurationMs = new LongSamplingCounter[freqCount][signalStrengthCount];
+ for (int freq = 0; freq < freqCount; freq++) {
+ for (int strength = 0; strength < signalStrengthCount; strength++) {
+ mPerStateTxDurationMs[freq][strength] = new LongSamplingCounter(timeBase);
+ }
+ }
+ }
+ if (frequencyRange < 0 || frequencyRange >= getFrequencyRangeCount()) {
+ Slog.w(TAG, "Unexpected frequency range (" + frequencyRange
+ + ") requested in getTxDurationCounter");
+ return null;
+ }
+ if (signalStrength < 0 || signalStrength >= perStateTimers[0].length) {
+ Slog.w(TAG, "Unexpected signal strength (" + signalStrength
+ + ") requested in getTxDurationCounter");
+ return null;
+ }
+ return mPerStateTxDurationMs[frequencyRange][signalStrength];
+ }
+
+ private LongSamplingCounter getRxDurationCounter(
+ @ServiceState.FrequencyRange int frequencyRange, boolean make) {
+ if (mPerFrequencyRxDurationMs == null) {
+ if (!make) return null;
+
+ final int freqCount = getFrequencyRangeCount();
+ final TimeBase timeBase = perStateTimers[0][0].mTimeBase;
+ mPerFrequencyRxDurationMs = new LongSamplingCounter[freqCount];
+ for (int freq = 0; freq < freqCount; freq++) {
+ mPerFrequencyRxDurationMs[freq] = new LongSamplingCounter(timeBase);
+ }
+ }
+ if (frequencyRange < 0 || frequencyRange >= getFrequencyRangeCount()) {
+ Slog.w(TAG, "Unexpected frequency range (" + frequencyRange
+ + ") requested in getRxDurationCounter");
+ return null;
+ }
+ return mPerFrequencyRxDurationMs[frequencyRange];
}
}
@@ -1929,18 +2122,26 @@
private final TimeBase mTimeBase;
private final LongMultiStateCounter mCounter;
- private TimeMultiStateCounter(TimeBase timeBase, Parcel in, long timestampMs) {
+ private TimeMultiStateCounter(TimeBase timeBase, int stateCount, long timestampMs) {
+ this(timeBase, new LongMultiStateCounter(stateCount), timestampMs);
+ }
+
+ private TimeMultiStateCounter(TimeBase timeBase, LongMultiStateCounter counter,
+ long timestampMs) {
mTimeBase = timeBase;
- mCounter = LongMultiStateCounter.CREATOR.createFromParcel(in);
+ mCounter = counter;
mCounter.setEnabled(mTimeBase.isRunning(), timestampMs);
timeBase.add(this);
}
- private TimeMultiStateCounter(TimeBase timeBase, int stateCount, long timestampMs) {
- mTimeBase = timeBase;
- mCounter = new LongMultiStateCounter(stateCount);
- mCounter.setEnabled(mTimeBase.isRunning(), timestampMs);
- timeBase.add(this);
+ @Nullable
+ private static TimeMultiStateCounter readFromParcel(Parcel in, TimeBase timeBase,
+ int stateCount, long timestampMs) {
+ LongMultiStateCounter counter = LongMultiStateCounter.CREATOR.createFromParcel(in);
+ if (counter.getStateCount() != stateCount) {
+ return null;
+ }
+ return new TimeMultiStateCounter(timeBase, counter, timestampMs);
}
private void writeToParcel(Parcel out) {
@@ -3510,11 +3711,8 @@
private TimeMultiStateCounter readTimeMultiStateCounter(Parcel in, TimeBase timeBase) {
if (in.readBoolean()) {
- final TimeMultiStateCounter counter =
- new TimeMultiStateCounter(timeBase, in, mClock.elapsedRealtime());
- if (counter.getStateCount() == BatteryConsumer.PROCESS_STATE_COUNT) {
- return counter;
- }
+ return TimeMultiStateCounter.readFromParcel(in, timeBase,
+ BatteryConsumer.PROCESS_STATE_COUNT, mClock.elapsedRealtime());
}
return null;
}
@@ -3537,9 +3735,10 @@
// invalid.
TimeMultiStateCounter[] counters = new TimeMultiStateCounter[numCounters];
for (int i = 0; i < numCounters; i++) {
- final TimeMultiStateCounter counter =
- new TimeMultiStateCounter(timeBase, in, mClock.elapsedRealtime());
- if (counter.getStateCount() == BatteryConsumer.PROCESS_STATE_COUNT) {
+ final TimeMultiStateCounter counter = TimeMultiStateCounter.readFromParcel(in,
+ timeBase, BatteryConsumer.PROCESS_STATE_COUNT,
+ mClock.elapsedRealtime());
+ if (counter != null) {
counters[i] = counter;
} else {
valid = false;
@@ -4564,8 +4763,11 @@
if (Process.isSdkSandboxUid(uid)) {
return Process.getAppUidForSdkSandboxUid(uid);
}
- int isolated = mIsolatedUids.get(uid, -1);
- return isolated > 0 ? isolated : uid;
+ return mapIsolatedUid(uid);
+ }
+
+ private int mapIsolatedUid(int uid) {
+ return mIsolatedUids.get(/*key=*/uid, /*valueIfKeyNotFound=*/uid);
}
@GuardedBy("this")
@@ -5016,7 +5218,7 @@
FrameworkStatsLog.WAKELOCK_STATE_CHANGED__STATE__ACQUIRE);
} else {
FrameworkStatsLog.write_non_chained(FrameworkStatsLog.WAKELOCK_STATE_CHANGED,
- mappedUid, null, getPowerManagerWakeLockLevel(type), name,
+ mapIsolatedUid(uid), null, getPowerManagerWakeLockLevel(type), name,
FrameworkStatsLog.WAKELOCK_STATE_CHANGED__STATE__ACQUIRE);
}
}
@@ -5070,7 +5272,7 @@
FrameworkStatsLog.WAKELOCK_STATE_CHANGED__STATE__RELEASE);
} else {
FrameworkStatsLog.write_non_chained(FrameworkStatsLog.WAKELOCK_STATE_CHANGED,
- mappedUid, null, getPowerManagerWakeLockLevel(type), name,
+ mapIsolatedUid(uid), null, getPowerManagerWakeLockLevel(type), name,
FrameworkStatsLog.WAKELOCK_STATE_CHANGED__STATE__RELEASE);
}
@@ -5494,7 +5696,10 @@
@GuardedBy("this")
private void noteStartGpsLocked(int uid, WorkChain workChain,
long elapsedRealtimeMs, long uptimeMs) {
- uid = getAttributionUid(uid, workChain);
+ if (workChain != null) {
+ uid = workChain.getAttributionUid();
+ }
+ final int mappedUid = mapUid(uid);
if (mGpsNesting == 0) {
mHistoryCur.states |= HistoryItem.STATE_GPS_ON_FLAG;
if (DEBUG_HISTORY) Slog.v(TAG, "Start GPS to: "
@@ -5504,21 +5709,24 @@
mGpsNesting++;
if (workChain == null) {
- FrameworkStatsLog.write_non_chained(FrameworkStatsLog.GPS_SCAN_STATE_CHANGED, uid, null,
- FrameworkStatsLog.GPS_SCAN_STATE_CHANGED__STATE__ON);
+ FrameworkStatsLog.write_non_chained(FrameworkStatsLog.GPS_SCAN_STATE_CHANGED,
+ mapIsolatedUid(uid), null, FrameworkStatsLog.GPS_SCAN_STATE_CHANGED__STATE__ON);
} else {
FrameworkStatsLog.write(FrameworkStatsLog.GPS_SCAN_STATE_CHANGED,
workChain.getUids(), workChain.getTags(),
FrameworkStatsLog.GPS_SCAN_STATE_CHANGED__STATE__ON);
}
- getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs).noteStartGps(elapsedRealtimeMs);
+ getUidStatsLocked(mappedUid, elapsedRealtimeMs, uptimeMs).noteStartGps(elapsedRealtimeMs);
}
@GuardedBy("this")
private void noteStopGpsLocked(int uid, WorkChain workChain,
long elapsedRealtimeMs, long uptimeMs) {
- uid = getAttributionUid(uid, workChain);
+ if (workChain != null) {
+ uid = workChain.getAttributionUid();
+ }
+ final int mappedUid = mapUid(uid);
mGpsNesting--;
if (mGpsNesting == 0) {
mHistoryCur.states &= ~HistoryItem.STATE_GPS_ON_FLAG;
@@ -5530,14 +5738,15 @@
}
if (workChain == null) {
- FrameworkStatsLog.write_non_chained(FrameworkStatsLog.GPS_SCAN_STATE_CHANGED, uid, null,
+ FrameworkStatsLog.write_non_chained(FrameworkStatsLog.GPS_SCAN_STATE_CHANGED,
+ mapIsolatedUid(uid), null,
FrameworkStatsLog.GPS_SCAN_STATE_CHANGED__STATE__OFF);
} else {
FrameworkStatsLog.write(FrameworkStatsLog.GPS_SCAN_STATE_CHANGED, workChain.getUids(),
workChain.getTags(), FrameworkStatsLog.GPS_SCAN_STATE_CHANGED__STATE__OFF);
}
- getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs).noteStopGps(elapsedRealtimeMs);
+ getUidStatsLocked(mappedUid, elapsedRealtimeMs, uptimeMs).noteStopGps(elapsedRealtimeMs);
}
@GuardedBy("this")
@@ -6955,7 +7164,10 @@
@GuardedBy("this")
private void noteBluetoothScanStartedLocked(WorkChain workChain, int uid,
boolean isUnoptimized, long elapsedRealtimeMs, long uptimeMs) {
- uid = getAttributionUid(uid, workChain);
+ if (workChain != null) {
+ uid = workChain.getAttributionUid();
+ }
+ uid = mapUid(uid);
if (mBluetoothScanNesting == 0) {
mHistoryCur.states2 |= HistoryItem.STATE2_BLUETOOTH_SCAN_FLAG;
if (DEBUG_HISTORY) Slog.v(TAG, "BLE scan started for: "
@@ -6995,7 +7207,10 @@
@GuardedBy("this")
private void noteBluetoothScanStoppedLocked(WorkChain workChain, int uid,
boolean isUnoptimized, long elapsedRealtimeMs, long uptimeMs) {
- uid = getAttributionUid(uid, workChain);
+ if (workChain != null) {
+ uid = workChain.getAttributionUid();
+ }
+ uid = mapUid(uid);
mBluetoothScanNesting--;
if (mBluetoothScanNesting == 0) {
mHistoryCur.states2 &= ~HistoryItem.STATE2_BLUETOOTH_SCAN_FLAG;
@@ -7008,14 +7223,6 @@
.noteBluetoothScanStoppedLocked(elapsedRealtimeMs, isUnoptimized);
}
- private int getAttributionUid(int uid, WorkChain workChain) {
- if (workChain != null) {
- return mapUid(workChain.getAttributionUid());
- }
-
- return mapUid(uid);
- }
-
@GuardedBy("this")
public void noteBluetoothScanStoppedFromSourceLocked(WorkSource ws, boolean isUnoptimized) {
noteBluetoothScanStoppedFromSourceLocked(ws, isUnoptimized,
@@ -8000,6 +8207,32 @@
elapsedRealtimeMs * 1000, STATS_SINCE_CHARGED) / 1000;
}
+ @Override
+ public long getActiveTxRadioDurationMs(@RadioAccessTechnology int rat,
+ @ServiceState.FrequencyRange int frequencyRange, int signalStrength,
+ long elapsedRealtimeMs) {
+ final RadioAccessTechnologyBatteryStats stats = mPerRatBatteryStats[rat];
+ if (stats == null) return DURATION_UNAVAILABLE;
+
+ final LongSamplingCounter counter = stats.getTxDurationCounter(frequencyRange,
+ signalStrength, false);
+ if (counter == null) return DURATION_UNAVAILABLE;
+
+ return counter.getCountLocked(STATS_SINCE_CHARGED);
+ }
+
+ @Override
+ public long getActiveRxRadioDurationMs(@RadioAccessTechnology int rat,
+ @ServiceState.FrequencyRange int frequencyRange, long elapsedRealtimeMs) {
+ final RadioAccessTechnologyBatteryStats stats = mPerRatBatteryStats[rat];
+ if (stats == null) return DURATION_UNAVAILABLE;
+
+ final LongSamplingCounter counter = stats.getRxDurationCounter(frequencyRange, false);
+ if (counter == null) return DURATION_UNAVAILABLE;
+
+ return counter.getCountLocked(STATS_SINCE_CHARGED);
+ }
+
@UnsupportedAppUsage
@Override public long getMobileRadioActiveTime(long elapsedRealtimeUs, int which) {
return mMobileRadioActiveTimer.getTotalTimeLocked(elapsedRealtimeUs, which);
@@ -10744,11 +10977,9 @@
= new LongSamplingCounter(mBsi.mOnBatteryTimeBase, in);
}
if (in.readBoolean()) {
- final TimeMultiStateCounter counter =
- new TimeMultiStateCounter(mBsi.mOnBatteryTimeBase, in, timestampMs);
- if (counter.getStateCount() == BatteryConsumer.PROCESS_STATE_COUNT) {
- mMobileRadioActiveTime = counter;
- }
+ mMobileRadioActiveTime = TimeMultiStateCounter.readFromParcel(in,
+ mBsi.mOnBatteryTimeBase, BatteryConsumer.PROCESS_STATE_COUNT,
+ timestampMs);
}
mMobileRadioActiveCount = new LongSamplingCounter(mBsi.mOnBatteryTimeBase, in);
@@ -10794,11 +11025,9 @@
int stateCount = in.readInt();
if (stateCount != 0) {
- final TimeMultiStateCounter counter = new TimeMultiStateCounter(
- mBsi.mOnBatteryTimeBase, in, timestampMs);
- if (stateCount == BatteryConsumer.PROCESS_STATE_COUNT) {
- mCpuActiveTimeMs = counter;
- }
+ mCpuActiveTimeMs = TimeMultiStateCounter.readFromParcel(in,
+ mBsi.mOnBatteryTimeBase, BatteryConsumer.PROCESS_STATE_COUNT,
+ timestampMs);
}
mCpuClusterTimesMs = new LongSamplingCounterArray(mBsi.mOnBatteryTimeBase, in);
@@ -13482,6 +13711,67 @@
addHistoryRecordLocked(elapsedRealtimeMs, uptimeMs);
mTmpRailStats.resetCellularTotalEnergyUsed();
}
+
+ // Proportionally smear Rx and Tx times across each RAt
+ final int levelCount = CellSignalStrength.getNumSignalStrengthLevels();
+ long[] perSignalStrengthActiveTimeMs = new long[levelCount];
+ long totalActiveTimeMs = 0;
+
+ for (int rat = 0; rat < RADIO_ACCESS_TECHNOLOGY_COUNT; rat++) {
+ final RadioAccessTechnologyBatteryStats ratStats = mPerRatBatteryStats[rat];
+ if (ratStats == null) continue;
+
+ final int freqCount = ratStats.getFrequencyRangeCount();
+ for (int freq = 0; freq < freqCount; freq++) {
+ for (int level = 0; level < levelCount; level++) {
+ final long durationMs = ratStats.getTimeSinceMark(freq, level,
+ elapsedRealtimeMs);
+ perSignalStrengthActiveTimeMs[level] += durationMs;
+ totalActiveTimeMs += durationMs;
+ }
+ }
+ }
+
+ if (totalActiveTimeMs != 0) {
+ // Smear the provided Tx/Rx durations across each RAT, frequency, and signal
+ // strength.
+ for (int rat = 0; rat < RADIO_ACCESS_TECHNOLOGY_COUNT; rat++) {
+ final RadioAccessTechnologyBatteryStats ratStats = mPerRatBatteryStats[rat];
+ if (ratStats == null) continue;
+
+ final int freqCount = ratStats.getFrequencyRangeCount();
+ for (int freq = 0; freq < freqCount; freq++) {
+ long frequencyDurationMs = 0;
+ for (int level = 0; level < levelCount; level++) {
+ final long durationMs = ratStats.getTimeSinceMark(freq, level,
+ elapsedRealtimeMs);
+ final long totalLvlDurationMs =
+ perSignalStrengthActiveTimeMs[level];
+ if (totalLvlDurationMs == 0) continue;
+ final long totalTxLvlDurations =
+ deltaInfo.getTransmitDurationMillisAtPowerLevel(level);
+ // Smear HAL provided Tx power level duration based on active modem
+ // duration in a given state. (Add totalLvlDurationMs / 2 before
+ // the integer division with totalLvlDurationMs for rounding.)
+ final long proportionalTxDurationMs =
+ (durationMs * totalTxLvlDurations
+ + (totalLvlDurationMs / 2)) / totalLvlDurationMs;
+ ratStats.incrementTxDuration(freq, level, proportionalTxDurationMs);
+ frequencyDurationMs += durationMs;
+ }
+ final long totalRxDuration = deltaInfo.getReceiveTimeMillis();
+ // Smear HAL provided Rx power duration based on active modem
+ // duration in a given state. (Add totalActiveTimeMs / 2 before the
+ // integer division with totalActiveTimeMs for rounding.)
+ final long proportionalRxDurationMs =
+ (frequencyDurationMs * totalRxDuration + (totalActiveTimeMs
+ / 2)) / totalActiveTimeMs;
+ ratStats.incrementRxDuration(freq, proportionalRxDurationMs);
+ }
+
+ ratStats.setMark(elapsedRealtimeMs);
+ }
+ }
}
long totalAppRadioTimeUs = mMobileRadioActivePerAppTimer.getTimeSinceMarkLocked(
elapsedRealtimeMs * 1000);
@@ -16887,14 +17177,18 @@
mNextMaxDailyDeadlineMs = in.readLong();
mBatteryTimeToFullSeconds = in.readLong();
- mMeasuredEnergyStatsConfig = MeasuredEnergyStats.Config.createFromParcel(in);
-
- /**
- * WARNING: Supported buckets may have changed across boots. Bucket mismatch is handled
- * later when {@link #initMeasuredEnergyStatsLocked} is called.
- */
- mGlobalMeasuredEnergyStats = MeasuredEnergyStats.createAndReadSummaryFromParcel(
- mMeasuredEnergyStatsConfig, in);
+ final MeasuredEnergyStats.Config config = MeasuredEnergyStats.Config.createFromParcel(in);
+ final MeasuredEnergyStats measuredEnergyStats =
+ MeasuredEnergyStats.createAndReadSummaryFromParcel(mMeasuredEnergyStatsConfig, in);
+ if (config != null && Arrays.equals(config.getStateNames(),
+ getBatteryConsumerProcessStateNames())) {
+ /**
+ * WARNING: Supported buckets may have changed across boots. Bucket mismatch is handled
+ * later when {@link #initMeasuredEnergyStatsLocked} is called.
+ */
+ mMeasuredEnergyStatsConfig = config;
+ mGlobalMeasuredEnergyStats = measuredEnergyStats;
+ }
mStartCount++;
@@ -16926,6 +17220,13 @@
mNetworkByteActivityCounters[i].readSummaryFromParcelLocked(in);
mNetworkPacketActivityCounters[i].readSummaryFromParcelLocked(in);
}
+
+ final int numRat = in.readInt();
+ for (int i = 0; i < numRat; i++) {
+ if (in.readInt() == 0) continue;
+ getRatBatteryStatsLocked(i).readSummaryFromParcel(in);
+ }
+
mMobileRadioPowerState = DataConnectionRealTimeInfo.DC_POWER_STATE_LOW;
mMobileRadioActiveTimer.readSummaryFromParcelLocked(in);
mMobileRadioActivePerAppTimer.readSummaryFromParcelLocked(in);
@@ -16986,7 +17287,6 @@
getScreenOffRpmTimerLocked(rpmName).readSummaryFromParcelLocked(in);
}
}
-
int NKW = in.readInt();
if (NKW > 10000) {
throw new ParcelFormatException("File corrupt: too many kernel wake locks " + NKW);
@@ -17114,11 +17414,9 @@
u.mNetworkPacketActivityCounters[i].readSummaryFromParcelLocked(in);
}
if (in.readBoolean()) {
- TimeMultiStateCounter counter = new TimeMultiStateCounter(
- mOnBatteryTimeBase, in, elapsedRealtimeMs);
- if (counter.getStateCount() == BatteryConsumer.PROCESS_STATE_COUNT) {
- u.mMobileRadioActiveTime = counter;
- }
+ u.mMobileRadioActiveTime = TimeMultiStateCounter.readFromParcel(in,
+ mOnBatteryTimeBase, BatteryConsumer.PROCESS_STATE_COUNT,
+ elapsedRealtimeMs);
}
u.mMobileRadioActiveCount.readSummaryFromParcelLocked(in);
}
@@ -17168,11 +17466,9 @@
int stateCount = in.readInt();
if (stateCount != 0) {
- final TimeMultiStateCounter counter = new TimeMultiStateCounter(
- mOnBatteryTimeBase, in, mClock.elapsedRealtime());
- if (stateCount == BatteryConsumer.PROCESS_STATE_COUNT) {
- u.mCpuActiveTimeMs = counter;
- }
+ u.mCpuActiveTimeMs = TimeMultiStateCounter.readFromParcel(in,
+ mOnBatteryTimeBase, BatteryConsumer.PROCESS_STATE_COUNT,
+ mClock.elapsedRealtime());
}
u.mCpuClusterTimesMs.readSummaryFromParcelLocked(in);
@@ -17431,6 +17727,17 @@
mNetworkByteActivityCounters[i].writeSummaryFromParcelLocked(out);
mNetworkPacketActivityCounters[i].writeSummaryFromParcelLocked(out);
}
+ final int numRat = mPerRatBatteryStats.length;
+ out.writeInt(numRat);
+ for (int i = 0; i < numRat; i++) {
+ final RadioAccessTechnologyBatteryStats ratStat = mPerRatBatteryStats[i];
+ if (ratStat == null) {
+ out.writeInt(0);
+ continue;
+ }
+ out.writeInt(1);
+ ratStat.writeSummaryToParcel(out, nowRealtime);
+ }
mMobileRadioActiveTimer.writeSummaryFromParcelLocked(out, nowRealtime);
mMobileRadioActivePerAppTimer.writeSummaryFromParcelLocked(out, nowRealtime);
mMobileRadioActiveAdjustedTime.writeSummaryFromParcelLocked(out);
@@ -18007,9 +18314,15 @@
mLastWriteTimeMs = in.readLong();
mBatteryTimeToFullSeconds = in.readLong();
- mMeasuredEnergyStatsConfig = MeasuredEnergyStats.Config.createFromParcel(in);
- mGlobalMeasuredEnergyStats =
+
+ final MeasuredEnergyStats.Config config = MeasuredEnergyStats.Config.createFromParcel(in);
+ final MeasuredEnergyStats measuredEnergyStats =
MeasuredEnergyStats.createFromParcel(mMeasuredEnergyStatsConfig, in);
+ if (config != null && Arrays.equals(config.getStateNames(),
+ getBatteryConsumerProcessStateNames())) {
+ mMeasuredEnergyStatsConfig = config;
+ mGlobalMeasuredEnergyStats = measuredEnergyStats;
+ }
mRpmStats.clear();
int NRPMS = in.readInt();
diff --git a/core/java/com/android/internal/os/KernelAllocationStats.java b/core/java/com/android/internal/os/KernelAllocationStats.java
index 1c3f8b0..58d51e3 100644
--- a/core/java/com/android/internal/os/KernelAllocationStats.java
+++ b/core/java/com/android/internal/os/KernelAllocationStats.java
@@ -24,21 +24,29 @@
/** Process dma-buf stats. */
public static final class ProcessDmabuf {
+ public final int uid;
+ public final String processName;
+ public final int oomScore;
+
/** Size of buffers retained by the process. */
public final int retainedSizeKb;
/** Number of buffers retained by the process. */
public final int retainedBuffersCount;
- /** Size of buffers mapped to the address space. */
- public final int mappedSizeKb;
- /** Count of buffers mapped to the address space. */
- public final int mappedBuffersCount;
+ /** Size of buffers shared with Surface Flinger. */
+ public final int surfaceFlingerSizeKb;
+ /** Count of buffers shared with Surface Flinger. */
+ public final int surfaceFlingerCount;
- ProcessDmabuf(int retainedSizeKb, int retainedBuffersCount,
- int mappedSizeKb, int mappedBuffersCount) {
+ ProcessDmabuf(int uid, String processName, int oomScore, int retainedSizeKb,
+ int retainedBuffersCount, int surfaceFlingerSizeKb,
+ int surfaceFlingerCount) {
+ this.uid = uid;
+ this.processName = processName;
+ this.oomScore = oomScore;
this.retainedSizeKb = retainedSizeKb;
this.retainedBuffersCount = retainedBuffersCount;
- this.mappedSizeKb = mappedSizeKb;
- this.mappedBuffersCount = mappedBuffersCount;
+ this.surfaceFlingerSizeKb = surfaceFlingerSizeKb;
+ this.surfaceFlingerCount = surfaceFlingerCount;
}
}
@@ -47,7 +55,7 @@
* stats could not be read.
*/
@Nullable
- public static native ProcessDmabuf getDmabufAllocations(int pid);
+ public static native ProcessDmabuf[] getDmabufAllocations();
/** Pid to gpu memory size. */
public static final class ProcessGpuMem {
diff --git a/core/java/com/android/internal/power/MeasuredEnergyStats.java b/core/java/com/android/internal/power/MeasuredEnergyStats.java
index 7262e84..7fb8696 100644
--- a/core/java/com/android/internal/power/MeasuredEnergyStats.java
+++ b/core/java/com/android/internal/power/MeasuredEnergyStats.java
@@ -194,6 +194,7 @@
return mSupportedMultiStateBuckets[index];
}
+ @NonNull
public String[] getStateNames() {
return mStateNames;
}
@@ -321,6 +322,10 @@
LongMultiStateCounter multiStateCounter = null;
if (in.readBoolean()) {
multiStateCounter = LongMultiStateCounter.CREATOR.createFromParcel(in);
+ if (mConfig == null
+ || multiStateCounter.getStateCount() != mConfig.getStateNames().length) {
+ multiStateCounter = null;
+ }
}
if (index < mAccumulatedChargeMicroCoulomb.length) {
diff --git a/core/java/com/android/internal/util/LatencyTracker.java b/core/java/com/android/internal/util/LatencyTracker.java
index 1cd758c..3f7c4d5 100644
--- a/core/java/com/android/internal/util/LatencyTracker.java
+++ b/core/java/com/android/internal/util/LatencyTracker.java
@@ -132,6 +132,11 @@
*/
public static final int ACTION_UDFPS_ILLUMINATE = 14;
+ /**
+ * Time it takes for the gesture back affordance arrow to show up.
+ */
+ public static final int ACTION_SHOW_BACK_ARROW = 15;
+
private static final int[] ACTIONS_ALL = {
ACTION_EXPAND_PANEL,
ACTION_TOGGLE_RECENTS,
@@ -147,7 +152,8 @@
ACTION_LOCKSCREEN_UNLOCK,
ACTION_USER_SWITCH,
ACTION_SWITCH_DISPLAY_UNFOLD,
- ACTION_UDFPS_ILLUMINATE
+ ACTION_UDFPS_ILLUMINATE,
+ ACTION_SHOW_BACK_ARROW,
};
/** @hide */
@@ -166,7 +172,8 @@
ACTION_LOCKSCREEN_UNLOCK,
ACTION_USER_SWITCH,
ACTION_SWITCH_DISPLAY_UNFOLD,
- ACTION_UDFPS_ILLUMINATE
+ ACTION_UDFPS_ILLUMINATE,
+ ACTION_SHOW_BACK_ARROW
})
@Retention(RetentionPolicy.SOURCE)
public @interface Action {
@@ -187,7 +194,8 @@
FrameworkStatsLog.UIACTION_LATENCY_REPORTED__ACTION__ACTION_LOCKSCREEN_UNLOCK,
FrameworkStatsLog.UIACTION_LATENCY_REPORTED__ACTION__ACTION_USER_SWITCH,
FrameworkStatsLog.UIACTION_LATENCY_REPORTED__ACTION__ACTION_SWITCH_DISPLAY_UNFOLD,
- FrameworkStatsLog.UIACTION_LATENCY_REPORTED__ACTION__ACTION_UDFPS_ILLUMINATE
+ FrameworkStatsLog.UIACTION_LATENCY_REPORTED__ACTION__ACTION_UDFPS_ILLUMINATE,
+ FrameworkStatsLog.UIACTION_LATENCY_REPORTED__ACTION__ACTION_SHOW_BACK_ARROW,
};
private static LatencyTracker sLatencyTracker;
@@ -277,6 +285,8 @@
return "ACTION_SWITCH_DISPLAY_UNFOLD";
case 15:
return "ACTION_UDFPS_ILLUMINATE";
+ case 16:
+ return "ACTION_SHOW_BACK_ARROW";
default:
throw new IllegalArgumentException("Invalid action");
}
diff --git a/core/java/com/android/internal/view/BaseIWindow.java b/core/java/com/android/internal/view/BaseIWindow.java
index 6673f67..842d72a 100644
--- a/core/java/com/android/internal/view/BaseIWindow.java
+++ b/core/java/com/android/internal/view/BaseIWindow.java
@@ -51,10 +51,10 @@
@Override
public void resized(ClientWindowFrames frames, boolean reportDraw,
MergedConfiguration mergedConfiguration, boolean forceLayout,
- boolean alwaysConsumeSystemBars, int displayId) {
+ boolean alwaysConsumeSystemBars, int displayId, int seqId) {
if (reportDraw) {
try {
- mSession.finishDrawing(this, null /* postDrawTransaction */);
+ mSession.finishDrawing(this, null /* postDrawTransaction */, seqId);
} catch (RemoteException e) {
}
}
diff --git a/core/java/com/android/internal/widget/ILockSettings.aidl b/core/java/com/android/internal/widget/ILockSettings.aidl
index 851e8e0..3494c9e 100644
--- a/core/java/com/android/internal/widget/ILockSettings.aidl
+++ b/core/java/com/android/internal/widget/ILockSettings.aidl
@@ -53,7 +53,6 @@
VerifyCredentialResponse verifyTiedProfileChallenge(in LockscreenCredential credential, int userId, int flags);
VerifyCredentialResponse verifyGatekeeperPasswordHandle(long gatekeeperPasswordHandle, long challenge, int userId);
void removeGatekeeperPasswordHandle(long gatekeeperPasswordHandle);
- boolean checkVoldPassword(int userId);
int getCredentialType(int userId);
byte[] getHashFactor(in LockscreenCredential currentCredential, int userId);
void setSeparateProfileChallengeEnabled(int userId, boolean enabled, in LockscreenCredential managedUserPassword);
diff --git a/core/java/com/android/internal/widget/LockPatternUtils.java b/core/java/com/android/internal/widget/LockPatternUtils.java
index 521b2f6..a94b307 100644
--- a/core/java/com/android/internal/widget/LockPatternUtils.java
+++ b/core/java/com/android/internal/widget/LockPatternUtils.java
@@ -526,20 +526,6 @@
}
/**
- * Check to see if vold already has the password.
- * Note that this also clears vold's copy of the password.
- * @return Whether the vold password matches or not.
- */
- public boolean checkVoldPassword(int userId) {
- try {
- return getLockSettings().checkVoldPassword(userId);
- } catch (RemoteException re) {
- Log.e(TAG, "failed to check vold password", re);
- return false;
- }
- }
-
- /**
* Returns the password history hash factor, needed to check new password against password
* history with {@link #checkPasswordHistory(byte[], byte[], int)}
*/
diff --git a/core/java/com/android/server/SystemConfig.java b/core/java/com/android/server/SystemConfig.java
index cc7e9d9..db41d33 100644
--- a/core/java/com/android/server/SystemConfig.java
+++ b/core/java/com/android/server/SystemConfig.java
@@ -31,9 +31,11 @@
import android.os.Process;
import android.os.SystemProperties;
import android.os.Trace;
+import android.os.VintfRuntimeInfo;
import android.os.incremental.IncrementalManager;
import android.os.storage.StorageManager;
import android.permission.PermissionManager.SplitPermissionInfo;
+import android.sysprop.ApexProperties;
import android.text.TextUtils;
import android.util.ArrayMap;
import android.util.ArraySet;
@@ -56,7 +58,10 @@
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
+import java.nio.charset.StandardCharsets;
+import java.nio.file.Files;
import java.nio.file.Path;
+import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
@@ -1187,7 +1192,8 @@
boolean systemExt = permFile.toPath().startsWith(
Environment.getSystemExtDirectory().toPath() + "/");
boolean apex = permFile.toPath().startsWith(
- Environment.getApexDirectory().toPath() + "/");
+ Environment.getApexDirectory().toPath() + "/")
+ && ApexProperties.updatable().orElse(false);
if (vendor) {
readPrivAppPermissions(parser, mVendorPrivAppPermissions,
mVendorPrivAppDenyPermissions);
@@ -1445,6 +1451,14 @@
addFeature(PackageManager.FEATURE_IPSEC_TUNNELS, 0);
}
+ if (isFilesystemSupported("erofs")) {
+ if (isKernelVersionAtLeast(5, 10)) {
+ addFeature(PackageManager.FEATURE_EROFS, 0);
+ } else if (isKernelVersionAtLeast(4, 19)) {
+ addFeature(PackageManager.FEATURE_EROFS_LEGACY, 0);
+ }
+ }
+
for (String featureName : mUnavailableFeatures) {
removeFeature(featureName);
}
@@ -1814,4 +1828,29 @@
private static boolean isSystemProcess() {
return Process.myUid() == Process.SYSTEM_UID;
}
+
+ private static boolean isFilesystemSupported(String fs) {
+ try {
+ final byte[] fsTableData = Files.readAllBytes(Paths.get("/proc/filesystems"));
+ final String fsTable = new String(fsTableData, StandardCharsets.UTF_8);
+ return fsTable.contains("\t" + fs + "\n");
+ } catch (Exception e) {
+ return false;
+ }
+ }
+
+ private static boolean isKernelVersionAtLeast(int major, int minor) {
+ final String kernelVersion = VintfRuntimeInfo.getKernelVersion();
+ final String[] parts = kernelVersion.split("\\.");
+ if (parts.length < 2) {
+ return false;
+ }
+ try {
+ final int majorVersion = Integer.parseInt(parts[0]);
+ final int minorVersion = Integer.parseInt(parts[1]);
+ return majorVersion > major || (majorVersion == major && minorVersion >= minor);
+ } catch (NumberFormatException e) {
+ return false;
+ }
+ }
}
diff --git a/core/jni/Android.bp b/core/jni/Android.bp
index 4aa00f6..a1be884 100644
--- a/core/jni/Android.bp
+++ b/core/jni/Android.bp
@@ -272,6 +272,7 @@
"libinput",
"libcamera_client",
"libcamera_metadata",
+ "libprocinfo",
"libsqlite",
"libEGL",
"libGLESv1_CM",
@@ -361,7 +362,7 @@
"libwuffs_mirror_release_c",
],
},
- linux_glibc: {
+ host_linux: {
srcs: [
"android_content_res_ApkAssets.cpp",
"android_database_CursorWindow.cpp",
diff --git a/core/jni/android_view_SurfaceControl.cpp b/core/jni/android_view_SurfaceControl.cpp
index 68025a8..39f192b 100644
--- a/core/jni/android_view_SurfaceControl.cpp
+++ b/core/jni/android_view_SurfaceControl.cpp
@@ -253,6 +253,11 @@
jfieldID alphaInterpretation;
} gDisplayDecorationSupportInfo;
+static struct {
+ jclass clazz;
+ jmethodID invokeReleaseCallback;
+} gInvokeReleaseCallback;
+
class JNamedColorSpace {
public:
// ColorSpace.Named.SRGB.ordinal() = 0;
@@ -625,8 +630,59 @@
transaction->setGeometry(ctrl, source, dst, orientation);
}
+class JGlobalRefHolder {
+public:
+ JGlobalRefHolder(JavaVM* vm, jobject object) : mVm(vm), mObject(object) {}
+
+ virtual ~JGlobalRefHolder() {
+ env()->DeleteGlobalRef(mObject);
+ mObject = nullptr;
+ }
+
+ jobject object() { return mObject; }
+ JavaVM* vm() { return mVm; }
+
+ JNIEnv* env() {
+ JNIEnv* env = nullptr;
+ if (mVm->GetEnv(reinterpret_cast<void**>(&env), JNI_VERSION_1_6) != JNI_OK) {
+ if (mVm->AttachCurrentThreadAsDaemon(&env, nullptr) != JNI_OK) {
+ LOG_ALWAYS_FATAL("Failed to AttachCurrentThread!");
+ }
+ }
+ return env;
+ }
+
+private:
+ JGlobalRefHolder(const JGlobalRefHolder&) = delete;
+ void operator=(const JGlobalRefHolder&) = delete;
+
+ JavaVM* mVm;
+ jobject mObject;
+};
+
+static ReleaseBufferCallback genReleaseCallback(JNIEnv* env, jobject releaseCallback) {
+ if (releaseCallback == nullptr) return nullptr;
+
+ JavaVM* vm = nullptr;
+ LOG_ALWAYS_FATAL_IF(env->GetJavaVM(&vm) != JNI_OK, "Unable to get Java VM");
+ auto globalCallbackRef =
+ std::make_shared<JGlobalRefHolder>(vm, env->NewGlobalRef(releaseCallback));
+ return [globalCallbackRef](const ReleaseCallbackId&, const sp<Fence>& releaseFence,
+ std::optional<uint32_t> currentMaxAcquiredBufferCount) {
+ Fence* fenceCopy = releaseFence.get();
+ // We need to grab an extra ref as Java's SyncFence takes ownership
+ if (fenceCopy) {
+ fenceCopy->incStrong(0);
+ }
+ globalCallbackRef->env()->CallStaticVoidMethod(gInvokeReleaseCallback.clazz,
+ gInvokeReleaseCallback.invokeReleaseCallback,
+ globalCallbackRef->object(),
+ reinterpret_cast<jlong>(fenceCopy));
+ };
+}
+
static void nativeSetBuffer(JNIEnv* env, jclass clazz, jlong transactionObj, jlong nativeObject,
- jobject bufferObject, jlong fencePtr) {
+ jobject bufferObject, jlong fencePtr, jobject releaseCallback) {
auto transaction = reinterpret_cast<SurfaceComposerClient::Transaction*>(transactionObj);
SurfaceControl* const ctrl = reinterpret_cast<SurfaceControl*>(nativeObject);
sp<GraphicBuffer> graphicBuffer(GraphicBuffer::fromAHardwareBuffer(
@@ -635,7 +691,8 @@
if (fencePtr != 0) {
optFence = sp<Fence>{reinterpret_cast<Fence*>(fencePtr)};
}
- transaction->setBuffer(ctrl, graphicBuffer, optFence);
+ transaction->setBuffer(ctrl, graphicBuffer, optFence, std::nullopt,
+ genReleaseCallback(env, releaseCallback));
}
static void nativeSetBufferTransform(JNIEnv* env, jclass clazz, jlong transactionObj,
@@ -2155,7 +2212,7 @@
(void*)nativeGetDisplayedContentSample },
{"nativeSetGeometry", "(JJLandroid/graphics/Rect;Landroid/graphics/Rect;J)V",
(void*)nativeSetGeometry },
- {"nativeSetBuffer", "(JJLandroid/hardware/HardwareBuffer;J)V",
+ {"nativeSetBuffer", "(JJLandroid/hardware/HardwareBuffer;JLjava/util/function/Consumer;)V",
(void*)nativeSetBuffer },
{"nativeSetBufferTransform", "(JJI)V", (void*) nativeSetBufferTransform},
{"nativeSetDataSpace", "(JJI)V",
@@ -2451,6 +2508,12 @@
gDisplayDecorationSupportInfo.alphaInterpretation =
GetFieldIDOrDie(env, displayDecorationSupportClazz, "alphaInterpretation", "I");
+ jclass surfaceControlClazz = FindClassOrDie(env, "android/view/SurfaceControl");
+ gInvokeReleaseCallback.clazz = MakeGlobalRefOrDie(env, surfaceControlClazz);
+ gInvokeReleaseCallback.invokeReleaseCallback =
+ GetStaticMethodIDOrDie(env, surfaceControlClazz, "invokeReleaseCallback",
+ "(Ljava/util/function/Consumer;J)V");
+
return err;
}
diff --git a/core/jni/android_window_WindowInfosListener.cpp b/core/jni/android_window_WindowInfosListener.cpp
index 08c9f20..aae2549 100644
--- a/core/jni/android_window_WindowInfosListener.cpp
+++ b/core/jni/android_window_WindowInfosListener.cpp
@@ -44,6 +44,11 @@
jmethodID ctor;
} gDisplayInfoClassInfo;
+static struct {
+ jclass clazz;
+ jmethodID ctor;
+} gPairClassInfo;
+
static jclass gInputWindowHandleClass;
jobject fromDisplayInfo(JNIEnv* env, gui::DisplayInfo displayInfo) {
@@ -57,6 +62,30 @@
displayInfo.logicalHeight, matrixObj.get());
}
+static jobjectArray fromWindowInfos(JNIEnv* env, const std::vector<WindowInfo>& windowInfos) {
+ jobjectArray jWindowHandlesArray =
+ env->NewObjectArray(windowInfos.size(), gInputWindowHandleClass, nullptr);
+ for (int i = 0; i < windowInfos.size(); i++) {
+ ScopedLocalRef<jobject>
+ jWindowHandle(env,
+ android_view_InputWindowHandle_fromWindowInfo(env, windowInfos[i]));
+ env->SetObjectArrayElement(jWindowHandlesArray, i, jWindowHandle.get());
+ }
+
+ return jWindowHandlesArray;
+}
+
+static jobjectArray fromDisplayInfos(JNIEnv* env, const std::vector<DisplayInfo>& displayInfos) {
+ jobjectArray jDisplayInfoArray =
+ env->NewObjectArray(displayInfos.size(), gDisplayInfoClassInfo.clazz, nullptr);
+ for (int i = 0; i < displayInfos.size(); i++) {
+ ScopedLocalRef<jobject> jDisplayInfo(env, fromDisplayInfo(env, displayInfos[i]));
+ env->SetObjectArrayElement(jDisplayInfoArray, i, jDisplayInfo.get());
+ }
+
+ return jDisplayInfoArray;
+}
+
struct WindowInfosListener : public gui::WindowInfosListener {
WindowInfosListener(JNIEnv* env, jobject listener)
: mListener(env->NewWeakGlobalRef(listener)) {}
@@ -72,26 +101,8 @@
return;
}
- ScopedLocalRef<jobjectArray>
- jWindowHandlesArray(env,
- env->NewObjectArray(windowInfos.size(), gInputWindowHandleClass,
- nullptr));
- for (int i = 0; i < windowInfos.size(); i++) {
- ScopedLocalRef<jobject>
- jWindowHandle(env,
- android_view_InputWindowHandle_fromWindowInfo(env,
- windowInfos[i]));
- env->SetObjectArrayElement(jWindowHandlesArray.get(), i, jWindowHandle.get());
- }
-
- ScopedLocalRef<jobjectArray>
- jDisplayInfoArray(env,
- env->NewObjectArray(displayInfos.size(),
- gDisplayInfoClassInfo.clazz, nullptr));
- for (int i = 0; i < displayInfos.size(); i++) {
- ScopedLocalRef<jobject> jDisplayInfo(env, fromDisplayInfo(env, displayInfos[i]));
- env->SetObjectArrayElement(jDisplayInfoArray.get(), i, jDisplayInfo.get());
- }
+ ScopedLocalRef<jobjectArray> jWindowHandlesArray(env, fromWindowInfos(env, windowInfos));
+ ScopedLocalRef<jobjectArray> jDisplayInfoArray(env, fromDisplayInfos(env, displayInfos));
env->CallVoidMethod(listener, gListenerClassInfo.onWindowInfosChanged,
jWindowHandlesArray.get(), jDisplayInfoArray.get());
@@ -124,9 +135,16 @@
listener->decStrong((void*)nativeCreate);
}
-void nativeRegister(JNIEnv* env, jclass clazz, jlong ptr) {
+jobject nativeRegister(JNIEnv* env, jclass clazz, jlong ptr) {
sp<WindowInfosListener> listener = reinterpret_cast<WindowInfosListener*>(ptr);
- SurfaceComposerClient::getDefault()->addWindowInfosListener(listener);
+ std::pair<std::vector<gui::WindowInfo>, std::vector<gui::DisplayInfo>> initialInfo;
+ SurfaceComposerClient::getDefault()->addWindowInfosListener(listener, &initialInfo);
+
+ ScopedLocalRef<jobjectArray> jWindowHandlesArray(env, fromWindowInfos(env, initialInfo.first));
+ ScopedLocalRef<jobjectArray> jDisplayInfoArray(env, fromDisplayInfos(env, initialInfo.second));
+
+ return env->NewObject(gPairClassInfo.clazz, gPairClassInfo.ctor, jWindowHandlesArray.get(),
+ jDisplayInfoArray.get());
}
void nativeUnregister(JNIEnv* env, jclass clazz, jlong ptr) {
@@ -141,7 +159,7 @@
const JNINativeMethod gMethods[] = {
/* name, signature, funcPtr */
{"nativeCreate", "(Landroid/window/WindowInfosListener;)J", (void*)nativeCreate},
- {"nativeRegister", "(J)V", (void*)nativeRegister},
+ {"nativeRegister", "(J)Landroid/util/Pair;", (void*)nativeRegister},
{"nativeUnregister", "(J)V", (void*)nativeUnregister},
{"nativeGetFinalizer", "()J", (void*)nativeGetFinalizer}};
@@ -166,6 +184,12 @@
gDisplayInfoClassInfo.clazz = MakeGlobalRefOrDie(env, clazz);
gDisplayInfoClassInfo.ctor = env->GetMethodID(gDisplayInfoClassInfo.clazz, "<init>",
"(IIILandroid/graphics/Matrix;)V");
+
+ clazz = env->FindClass("android/util/Pair");
+ gPairClassInfo.clazz = MakeGlobalRefOrDie(env, clazz);
+ gPairClassInfo.ctor = env->GetMethodID(gPairClassInfo.clazz, "<init>",
+ "(Ljava/lang/Object;Ljava/lang/Object;)V");
+
return 0;
}
diff --git a/core/jni/com_android_internal_os_KernelAllocationStats.cpp b/core/jni/com_android_internal_os_KernelAllocationStats.cpp
index e0a24430..5b10497 100644
--- a/core/jni/com_android_internal_os_KernelAllocationStats.cpp
+++ b/core/jni/com_android_internal_os_KernelAllocationStats.cpp
@@ -13,12 +13,19 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
+#include <android-base/logging.h>
+#include <android-base/stringprintf.h>
#include <dmabufinfo/dmabufinfo.h>
#include <jni.h>
#include <meminfo/sysmeminfo.h>
+#include <procinfo/process.h>
#include "core_jni_helpers.h"
+using DmaBuffer = ::android::dmabufinfo::DmaBuffer;
+using android::base::ReadFileToString;
+using android::base::StringPrintf;
+
namespace {
static jclass gProcessDmabufClazz;
static jmethodID gProcessDmabufCtor;
@@ -28,30 +35,127 @@
namespace android {
-static jobject KernelAllocationStats_getDmabufAllocations(JNIEnv *env, jobject, jint pid) {
- std::vector<dmabufinfo::DmaBuffer> buffers;
- if (!dmabufinfo::ReadDmaBufMapRefs(pid, &buffers)) {
+struct PidDmaInfo {
+ uid_t uid;
+ std::string cmdline;
+ int oomScoreAdj;
+};
+
+static jobjectArray KernelAllocationStats_getDmabufAllocations(JNIEnv *env, jobject) {
+ std::vector<DmaBuffer> buffers;
+
+ if (!dmabufinfo::ReadDmaBufs(&buffers)) {
return nullptr;
}
- jint mappedSize = 0;
- jint mappedCount = buffers.size();
- for (const auto &buffer : buffers) {
- mappedSize += buffer.size();
- }
- mappedSize /= 1024;
- jint retainedSize = -1;
- jint retainedCount = -1;
- if (dmabufinfo::ReadDmaBufFdRefs(pid, &buffers)) {
- retainedCount = buffers.size();
- retainedSize = 0;
- for (const auto &buffer : buffers) {
- retainedSize += buffer.size();
+ // Create a reverse map from pid to dmabufs
+ // Store dmabuf inodes & sizes for later processing.
+ std::unordered_map<pid_t, std::set<ino_t>> pidToInodes;
+ std::unordered_map<ino_t, long> inodeToSize;
+ for (auto &buf : buffers) {
+ for (auto pid : buf.pids()) {
+ pidToInodes[pid].insert(buf.inode());
}
- retainedSize /= 1024;
+ inodeToSize[buf.inode()] = buf.size();
}
- return env->NewObject(gProcessDmabufClazz, gProcessDmabufCtor, retainedSize, retainedCount,
- mappedSize, mappedCount);
+
+ pid_t surfaceFlingerPid = -1;
+ // The set of all inodes that are being retained by SurfaceFlinger. Buffers
+ // shared between another process and SF will appear in this set.
+ std::set<ino_t> surfaceFlingerBufferInodes;
+ // The set of all inodes that are being retained by any process other
+ // than SurfaceFlinger. Buffers shared between another process and SF will
+ // appear in this set.
+ std::set<ino_t> otherProcessBufferInodes;
+
+ // Find SurfaceFlinger pid & get cmdlines, oomScoreAdj, etc for each pid
+ // holding any DMA buffers.
+ std::unordered_map<pid_t, PidDmaInfo> pidDmaInfos;
+ for (const auto &pidToInodeEntry : pidToInodes) {
+ pid_t pid = pidToInodeEntry.first;
+
+ android::procinfo::ProcessInfo processInfo;
+ if (!android::procinfo::GetProcessInfo(pid, &processInfo)) {
+ continue;
+ }
+
+ std::string cmdline;
+ if (!ReadFileToString(StringPrintf("/proc/%d/cmdline", pid), &cmdline)) {
+ continue;
+ }
+
+ // cmdline strings are null-delimited, so we split on \0 here
+ if (cmdline.substr(0, cmdline.find('\0')) == "/system/bin/surfaceflinger") {
+ if (surfaceFlingerPid == -1) {
+ surfaceFlingerPid = pid;
+ surfaceFlingerBufferInodes = pidToInodes[pid];
+ } else {
+ LOG(ERROR) << "getDmabufAllocations found multiple SF processes; pid1: " << pid
+ << ", pid2:" << surfaceFlingerPid;
+ surfaceFlingerPid = -2; // Used as a sentinel value below
+ }
+ } else {
+ otherProcessBufferInodes.insert(pidToInodes[pid].begin(), pidToInodes[pid].end());
+ }
+
+ std::string oomScoreAdjStr;
+ if (!ReadFileToString(StringPrintf("/proc/%d/oom_score_adj", pid), &oomScoreAdjStr)) {
+ continue;
+ }
+
+ pidDmaInfos[pid] = PidDmaInfo{.uid = processInfo.uid,
+ .cmdline = cmdline,
+ .oomScoreAdj = atoi(oomScoreAdjStr.c_str())};
+ }
+
+ if (surfaceFlingerPid < 0) {
+ LOG(ERROR) << "getDmabufAllocations could not identify SurfaceFlinger "
+ << "process via /proc/pid/cmdline";
+ }
+
+ jobjectArray ret = env->NewObjectArray(pidDmaInfos.size(), gProcessDmabufClazz, NULL);
+ int retArrayIndex = 0;
+ for (const auto &pidDmaInfosEntry : pidDmaInfos) {
+ pid_t pid = pidDmaInfosEntry.first;
+
+ // For all processes apart from SurfaceFlinger, this set will store the
+ // dmabuf inodes that are shared with SF. For SF, it will store the inodes
+ // that are shared with any other process.
+ std::set<ino_t> sharedBuffers;
+ if (pid == surfaceFlingerPid) {
+ set_intersection(surfaceFlingerBufferInodes.begin(), surfaceFlingerBufferInodes.end(),
+ otherProcessBufferInodes.begin(), otherProcessBufferInodes.end(),
+ std::inserter(sharedBuffers, sharedBuffers.end()));
+ } else if (surfaceFlingerPid > 0) {
+ set_intersection(pidToInodes[pid].begin(), pidToInodes[pid].end(),
+ surfaceFlingerBufferInodes.begin(), surfaceFlingerBufferInodes.end(),
+ std::inserter(sharedBuffers, sharedBuffers.begin()));
+ } // If surfaceFlingerPid < 0; it means we failed to identify it, and
+ // the SF-related fields below should be left empty.
+
+ long totalSize = 0;
+ long sharedBuffersSize = 0;
+ for (const auto &inode : pidToInodes[pid]) {
+ totalSize += inodeToSize[inode];
+ if (sharedBuffers.count(inode)) {
+ sharedBuffersSize += inodeToSize[inode];
+ }
+ }
+
+ jobject obj = env->NewObject(gProcessDmabufClazz, gProcessDmabufCtor,
+ /* uid */ pidDmaInfos[pid].uid,
+ /* process name */
+ env->NewStringUTF(pidDmaInfos[pid].cmdline.c_str()),
+ /* oomscore */ pidDmaInfos[pid].oomScoreAdj,
+ /* retainedSize */ totalSize / 1024,
+ /* retainedCount */ pidToInodes[pid].size(),
+ /* sharedWithSurfaceFlinger size */ sharedBuffersSize / 1024,
+ /* sharedWithSurfaceFlinger count */ sharedBuffers.size());
+
+ env->SetObjectArrayElement(ret, retArrayIndex++, obj);
+ }
+
+ return ret;
}
static jobject KernelAllocationStats_getGpuAllocations(JNIEnv *env) {
@@ -74,7 +178,7 @@
}
static const JNINativeMethod methods[] = {
- {"getDmabufAllocations", "(I)Lcom/android/internal/os/KernelAllocationStats$ProcessDmabuf;",
+ {"getDmabufAllocations", "()[Lcom/android/internal/os/KernelAllocationStats$ProcessDmabuf;",
(void *)KernelAllocationStats_getDmabufAllocations},
{"getGpuAllocations", "()[Lcom/android/internal/os/KernelAllocationStats$ProcessGpuMem;",
(void *)KernelAllocationStats_getGpuAllocations},
@@ -86,7 +190,8 @@
jclass clazz =
FindClassOrDie(env, "com/android/internal/os/KernelAllocationStats$ProcessDmabuf");
gProcessDmabufClazz = MakeGlobalRefOrDie(env, clazz);
- gProcessDmabufCtor = GetMethodIDOrDie(env, gProcessDmabufClazz, "<init>", "(IIII)V");
+ gProcessDmabufCtor =
+ GetMethodIDOrDie(env, gProcessDmabufClazz, "<init>", "(ILjava/lang/String;IIIII)V");
clazz = FindClassOrDie(env, "com/android/internal/os/KernelAllocationStats$ProcessGpuMem");
gProcessGpuMemClazz = MakeGlobalRefOrDie(env, clazz);
@@ -94,4 +199,4 @@
return res;
}
-} // namespace android
+} // namespace android
\ No newline at end of file
diff --git a/core/proto/android/os/appbatterystats.proto b/core/proto/android/os/appbatterystats.proto
new file mode 100644
index 0000000..8769ebb
--- /dev/null
+++ b/core/proto/android/os/appbatterystats.proto
@@ -0,0 +1,47 @@
+/*
+ * 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 = "proto2";
+package android.os;
+
+option java_multiple_files = true;
+
+message AppBatteryStatsProto {
+ message UidStats {
+ optional int32 uid = 1;
+
+ message ProcessStateStats {
+ enum ProcessState {
+ UNSPECIFIED = 0;
+ FOREGROUND = 1;
+ BACKGROUND = 2;
+ FOREGROUND_SERVICE = 3;
+ CACHED = 4;
+ }
+
+ optional ProcessState process_state = 1;
+
+ // Time spent in this state in the past 24 hours
+ optional int64 duration_ms = 2;
+ // Estimated power consumed in this state in the past 24 hours
+ optional double power_mah = 3;
+ }
+
+ repeated ProcessStateStats process_state_stats = 2;
+ }
+
+ repeated UidStats uid_stats = 1;
+}
diff --git a/core/proto/android/os/batteryusagestats.proto b/core/proto/android/os/batteryusagestats.proto
index cc90e05..856bc83 100644
--- a/core/proto/android/os/batteryusagestats.proto
+++ b/core/proto/android/os/batteryusagestats.proto
@@ -76,6 +76,7 @@
FOREGROUND = 1;
BACKGROUND = 2;
FOREGROUND_SERVICE = 3;
+ CACHED = 4;
}
optional ProcessState process_state = 2;
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index d652b2f..6585bd3 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -528,6 +528,7 @@
<protected-broadcast android:name="android.intent.action.MANAGED_PROFILE_ADDED" />
<protected-broadcast android:name="android.intent.action.MANAGED_PROFILE_UNLOCKED" />
<protected-broadcast android:name="android.intent.action.MANAGED_PROFILE_REMOVED" />
+ <protected-broadcast android:name="android.app.action.MANAGED_PROFILE_PROVISIONED" />
<protected-broadcast android:name="android.bluetooth.adapter.action.BLE_STATE_CHANGED" />
<protected-broadcast android:name="com.android.bluetooth.map.USER_CONFIRM_TIMEOUT" />
@@ -720,10 +721,12 @@
<!-- Added in T -->
<protected-broadcast android:name="android.safetycenter.action.REFRESH_SAFETY_SOURCES" />
+ <protected-broadcast android:name="android.safetycenter.action.SAFETY_CENTER_ENABLED_CHANGED" />
<protected-broadcast android:name="android.app.action.DEVICE_POLICY_RESOURCE_UPDATED" />
<protected-broadcast android:name="android.intent.action.SHOW_FOREGROUND_SERVICE_MANAGER" />
<protected-broadcast android:name="android.service.autofill.action.DELAYED_FILL" />
<protected-broadcast android:name="android.app.action.PROVISIONING_COMPLETED" />
+ <protected-broadcast android:name="android.app.action.LOST_MODE_LOCATION_UPDATE" />
<!-- ====================================================================== -->
<!-- RUNTIME PERMISSIONS -->
@@ -991,10 +994,12 @@
<!-- Allows an application to read audio files from external storage.
<p>This permission is enforced starting in API level
- {@link android.os.Build.VERSION_CODES#TIRAMISU}.
+ {@link android.os.Build.VERSION_CODES#TIRAMISU}. An app which targets
+ {@link android.os.Build.VERSION_CODES#TIRAMISU} or higher and needs to read audio files from
+ external storage must hold this permission; {@link #READ_EXTERNAL_STORAGE} is not required.
For apps with a <a href="{@docRoot}guide/topics/manifest/uses-sdk-element.html#target">{@code
- targetSdkVersion}</a> of {@link android.os.Build.VERSION_CODES#S} or lower, this permission
- must not be used and the READ_EXTERNAL_STORAGE permission must be used instead.
+ targetSdkVersion}</a> of {@link android.os.Build.VERSION_CODES#S_V2} or lower, the
+ {@link #READ_EXTERNAL_STORAGE} permission is required, instead, to read audio files.
<p>Protection level: dangerous -->
<permission android:name="android.permission.READ_MEDIA_AUDIO"
android:permissionGroup="android.permission-group.UNDEFINED"
@@ -1010,12 +1015,14 @@
android:description="@string/permgroupdesc_readMediaVisual"
android:priority="1000" />
- <!-- Allows an application to read audio files from external storage.
- <p>This permission is enforced starting in API level
- {@link android.os.Build.VERSION_CODES#TIRAMISU}.
- For apps with a <a href="{@docRoot}guide/topics/manifest/uses-sdk-element.html#target">{@code
- targetSdkVersion}</a> of {@link android.os.Build.VERSION_CODES#S} or lower, this permission
- must not be used and the READ_EXTERNAL_STORAGE permission must be used instead.
+ <!-- Allows an application to read video files from external storage.
+ <p>This permission is enforced starting in API level
+ {@link android.os.Build.VERSION_CODES#TIRAMISU}. An app which targets
+ {@link android.os.Build.VERSION_CODES#TIRAMISU} or higher and needs to read video files from
+ external storage must hold this permission; {@link #READ_EXTERNAL_STORAGE} is not required.
+ For apps with a <a href="{@docRoot}guide/topics/manifest/uses-sdk-element.html#target">{@code
+ targetSdkVersion}</a> of {@link android.os.Build.VERSION_CODES#S_V2} or lower, the
+ {@link #READ_EXTERNAL_STORAGE} permission is required, instead, to read video files.
<p>Protection level: dangerous -->
<permission android:name="android.permission.READ_MEDIA_VIDEO"
android:permissionGroup="android.permission-group.UNDEFINED"
@@ -1025,11 +1032,13 @@
<!-- Allows an application to read image files from external storage.
<p>This permission is enforced starting in API level
- {@link android.os.Build.VERSION_CODES#TIRAMISU}.
+ {@link android.os.Build.VERSION_CODES#TIRAMISU}. An app which targets
+ {@link android.os.Build.VERSION_CODES#TIRAMISU} or higher and needs to read image files from
+ external storage must hold this permission; {@link #READ_EXTERNAL_STORAGE} is not required.
For apps with a <a href="{@docRoot}guide/topics/manifest/uses-sdk-element.html#target">{@code
- targetSdkVersion}</a> of {@link android.os.Build.VERSION_CODES#S} or lower, this permission
- must not be used and the READ_EXTERNAL_STORAGE permission must be used instead.
- <p>Protection level: dangerous -->
+ targetSdkVersion}</a> of {@link android.os.Build.VERSION_CODES#S_V2} or lower, the
+ {@link #READ_EXTERNAL_STORAGE} permission is required, instead, to read image files.
+ <p>Protection level: dangerous -->
<permission android:name="android.permission.READ_MEDIA_IMAGES"
android:permissionGroup="android.permission-group.UNDEFINED"
android:label="@string/permlab_readMediaImages"
@@ -5143,6 +5152,14 @@
android:protectionLevel="signature|privileged|development|appop|retailDemo" />
<uses-permission android:name="android.permission.PACKAGE_USAGE_STATS" />
+ <!-- Allows an application to query broadcast response stats (see
+ {@link android.app.usage.BroadcastResponseStats}).
+ @SystemApi
+ @hide
+ -->
+ <permission android:name="android.permission.ACCESS_BROADCAST_RESPONSE_STATS"
+ android:protectionLevel="signature|privileged|development" />
+
<!-- Allows a data loader to read a package's access logs. The access logs contain the
set of pages referenced over time.
<p>Declaring the permission implies intention to use the API and the user of the
@@ -6051,10 +6068,10 @@
<permission android:name="android.permission.MANAGE_APPOPS"
android:protectionLevel="signature" />
- <!-- @hide Permission that allows background clipboard access.
- <p>Not for use by third-party applications. -->
+ <!-- @SystemApi Permission that allows background clipboard access.
+ @hide Not for use by third-party applications. -->
<permission android:name="android.permission.READ_CLIPBOARD_IN_BACKGROUND"
- android:protectionLevel="signature" />
+ android:protectionLevel="signature|role" />
<!-- @hide Permission that suppresses the notification when the clipboard is accessed.
<p>Not for use by third-party applications. -->
<permission android:name="android.permission.SUPPRESS_CLIPBOARD_ACCESS_NOTIFICATION"
diff --git a/core/res/res/values/attrs.xml b/core/res/res/values/attrs.xml
index da5f899..2107f65 100644
--- a/core/res/res/values/attrs.xml
+++ b/core/res/res/values/attrs.xml
@@ -5479,9 +5479,9 @@
<enum name="none" value="0" />
<!-- Use the least restrictive rule for line-breaking. -->
<enum name="loose" value="1" />
- <!-- Indicate breaking text with the most comment set of line-breaking rules. -->
+ <!-- Indicates breaking text with the most comment set of line-breaking rules. -->
<enum name="normal" value="2" />
- <!-- ndicates breaking text with the most strictest line-breaking rules. -->
+ <!-- Indicates breaking text with the most strictest line-breaking rules. -->
<enum name="strict" value="3" />
</attr>
<!-- Specify the phrase-based line break can be used when calculating the text wrapping.-->
diff --git a/core/res/res/values/attrs_manifest.xml b/core/res/res/values/attrs_manifest.xml
index 579ef51..7562b9a 100644
--- a/core/res/res/values/attrs_manifest.xml
+++ b/core/res/res/values/attrs_manifest.xml
@@ -401,15 +401,6 @@
and before. -->
<attr name="sharedUserMaxSdkVersion" format="integer" />
- <!-- Whether the application should inherit all AndroidKeyStore keys of its shared user
- group in the case of leaving its shared user ID in an upgrade. If set to false, all
- AndroidKeyStore keys will remain in the shared user group, and the application will no
- longer have access to those keys after the upgrade. If set to true, all AndroidKeyStore
- keys owned by the shared user group will be transferred to the upgraded application;
- other applications in the shared user group will no longer have access to those keys
- after the migration. The default value is false if not explicitly set. -->
- <attr name="inheritKeyStoreKeys" format="boolean" />
-
<!-- Internal version code. This is the number used to determine whether
one version is more recent than another: it has no other meaning than
that higher numbers are more recent. You could use this number to
@@ -1704,7 +1695,6 @@
<attr name="sharedUserId" />
<attr name="sharedUserLabel" />
<attr name="sharedUserMaxSdkVersion" />
- <attr name="inheritKeyStoreKeys" />
<attr name="installLocation" />
<attr name="isolatedSplits" />
<attr name="isFeatureSplit" />
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index 269aa1b..0344a93 100644
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -4857,6 +4857,7 @@
<item>0.25</item>
<item>0.5</item>
<item>0.75</item>
+ <item>0.875</item>
</string-array>
<!-- Messages that should not be shown to the user during face auth enrollment. This should be
@@ -5741,13 +5742,13 @@
exceeds the threshold, it'll be moved to restricted standby bucket. The value must be
one of or combination of the definitions in AppBatteryPolicy.
-->
- <integer name="config_bg_current_drain_types_to_restricted_bucket">4</integer>
+ <integer name="config_bg_current_drain_types_to_restricted_bucket">20</integer>
<!-- The types of battery drain we're checking on each app; if the sum of the battery drain
exceeds the threshold, it'll be moved to background restricted level. The value must be
one of or combination of the definitions in AppBatteryPolicy.
-->
- <integer name="config_bg_current_drain_types_to_bg_restricted">12</integer>
+ <integer name="config_bg_current_drain_types_to_bg_restricted">28</integer>
<!-- The power usage components we're monitoring. Must one of the definition in BatteryConsumer.
-->
@@ -5795,7 +5796,7 @@
<!-- The types of state where we'll exempt its battery usage during that state.
The state here must be one or a combination of STATE_TYPE_* in BaseAppStateTracker.
-->
- <integer name="config_bg_current_drain_exempted_types">9</integer>
+ <integer name="config_bg_current_drain_exempted_types">25</integer>
<!-- The behavior when an app has the permission ACCESS_BACKGROUND_LOCATION granted,
whether or not the system will use a higher threshold towards its background battery usage
diff --git a/core/res/res/values/public-staging.xml b/core/res/res/values/public-staging.xml
index 2dc17b8..e35d2e9 100644
--- a/core/res/res/values/public-staging.xml
+++ b/core/res/res/values/public-staging.xml
@@ -128,7 +128,6 @@
<public name="localeConfig" />
<public name="showBackground" />
<public name="useTargetActivityForQuickAccess"/>
- <public name="inheritKeyStoreKeys" />
<public name="preferKeepClear" />
<public name="autoHandwritingEnabled" />
<public name="fromExtendLeft" />
diff --git a/core/tests/batterystatstests/BatteryStatsViewer/src/com/android/frameworks/core/batterystatsviewer/BatteryConsumerData.java b/core/tests/batterystatstests/BatteryStatsViewer/src/com/android/frameworks/core/batterystatsviewer/BatteryConsumerData.java
index 6a53f68..19bb718 100644
--- a/core/tests/batterystatstests/BatteryStatsViewer/src/com/android/frameworks/core/batterystatsviewer/BatteryConsumerData.java
+++ b/core/tests/batterystatstests/BatteryStatsViewer/src/com/android/frameworks/core/batterystatsviewer/BatteryConsumerData.java
@@ -188,6 +188,9 @@
case BatteryConsumer.PROCESS_STATE_FOREGROUND_SERVICE:
label = "FGS";
break;
+ case BatteryConsumer.PROCESS_STATE_CACHED:
+ label = "cached";
+ break;
default:
continue;
}
diff --git a/core/tests/batterystatstests/BatteryUsageStatsProtoTests/src/com/android/internal/os/BatteryUsageStatsPulledTest.java b/core/tests/batterystatstests/BatteryUsageStatsProtoTests/src/com/android/internal/os/BatteryUsageStatsPulledTest.java
index 23b12cf..fd08e3c 100644
--- a/core/tests/batterystatstests/BatteryUsageStatsProtoTests/src/com/android/internal/os/BatteryUsageStatsPulledTest.java
+++ b/core/tests/batterystatstests/BatteryUsageStatsProtoTests/src/com/android/internal/os/BatteryUsageStatsPulledTest.java
@@ -242,13 +242,17 @@
BatteryConsumer.PROCESS_STATE_BACKGROUND);
final BatteryConsumer.Key keyFgs = uidBuilder.getKey(BatteryConsumer.POWER_COMPONENT_CPU,
BatteryConsumer.PROCESS_STATE_FOREGROUND_SERVICE);
+ final BatteryConsumer.Key keyCached = uidBuilder.getKey(BatteryConsumer.POWER_COMPONENT_CPU,
+ BatteryConsumer.PROCESS_STATE_CACHED);
uidBuilder.setConsumedPower(keyFg, 9100, BatteryConsumer.POWER_MODEL_POWER_PROFILE)
.setUsageDurationMillis(keyFg, 8100)
.setConsumedPower(keyBg, 9200, BatteryConsumer.POWER_MODEL_MEASURED_ENERGY)
.setUsageDurationMillis(keyBg, 8200)
.setConsumedPower(keyFgs, 9300, BatteryConsumer.POWER_MODEL_MEASURED_ENERGY)
- .setUsageDurationMillis(keyFgs, 8300);
+ .setUsageDurationMillis(keyFgs, 8300)
+ .setConsumedPower(keyCached, 9400, BatteryConsumer.POWER_MODEL_MEASURED_ENERGY)
+ .setUsageDurationMillis(keyFgs, 8400);
builder.getOrCreateUidBatteryConsumerBuilder(batteryStatsUid1)
.setPackageWithHighestDrain("myPackage1")
diff --git a/core/tests/coretests/src/android/content/pm/CrossProfileAppsTest.java b/core/tests/coretests/src/android/content/pm/CrossProfileAppsTest.java
index fa657f7..5e07607 100644
--- a/core/tests/coretests/src/android/content/pm/CrossProfileAppsTest.java
+++ b/core/tests/coretests/src/android/content/pm/CrossProfileAppsTest.java
@@ -27,6 +27,7 @@
import static org.mockito.Mockito.when;
import android.app.admin.DevicePolicyManager;
+import android.app.admin.DevicePolicyResourcesManager;
import android.content.Context;
import android.content.res.Resources;
import android.graphics.drawable.Drawable;
@@ -66,6 +67,8 @@
@Mock
private DevicePolicyManager mDevicePolicyManager;
@Mock
+ private DevicePolicyResourcesManager mDevicePolicyResourcesManager;
+ @Mock
private ICrossProfileApps mService;
@Mock
private Resources mResources;
@@ -89,6 +92,7 @@
Context.DEVICE_POLICY_SERVICE);
when(mContext.getSystemService(Context.DEVICE_POLICY_SERVICE)).thenReturn(
mDevicePolicyManager);
+ when(mDevicePolicyManager.getResources()).thenReturn(mDevicePolicyResourcesManager);
when(mContext.getPackageManager()).thenReturn(mPackageManager);
}
@@ -113,7 +117,7 @@
setValidTargetProfile(MANAGED_PROFILE);
mCrossProfileApps.getProfileSwitchingLabel(MANAGED_PROFILE);
- verify(mDevicePolicyManager).getString(eq(SWITCH_TO_WORK_LABEL), any());
+ verify(mDevicePolicyResourcesManager).getString(eq(SWITCH_TO_WORK_LABEL), any());
}
@Test
@@ -121,7 +125,7 @@
setValidTargetProfile(PERSONAL_PROFILE);
mCrossProfileApps.getProfileSwitchingLabel(PERSONAL_PROFILE);
- verify(mDevicePolicyManager).getString(eq(SWITCH_TO_PERSONAL_LABEL), any());
+ verify(mDevicePolicyResourcesManager).getString(eq(SWITCH_TO_PERSONAL_LABEL), any());
}
@Test(expected = SecurityException.class)
diff --git a/core/tests/coretests/src/android/net/SntpClientTest.java b/core/tests/coretests/src/android/net/SntpClientTest.java
index ba7df1e..267fc2b 100644
--- a/core/tests/coretests/src/android/net/SntpClientTest.java
+++ b/core/tests/coretests/src/android/net/SntpClientTest.java
@@ -295,7 +295,8 @@
@Test
public void testDnsResolutionFailure() throws Exception {
- assertFalse(mClient.requestTime("ntp.server.doesnotexist.example", 5000, mNetwork));
+ assertFalse(mClient.requestTime("ntp.server.doesnotexist.example",
+ SntpClient.STANDARD_NTP_PORT, 5000, mNetwork));
}
@Test
diff --git a/core/tests/coretests/src/android/view/stylus/HandwritingInitiatorTest.java b/core/tests/coretests/src/android/view/stylus/HandwritingInitiatorTest.java
index 1ae9649..e303934 100644
--- a/core/tests/coretests/src/android/view/stylus/HandwritingInitiatorTest.java
+++ b/core/tests/coretests/src/android/view/stylus/HandwritingInitiatorTest.java
@@ -60,7 +60,7 @@
@RunWith(AndroidJUnit4.class)
public class HandwritingInitiatorTest {
private static final int TOUCH_SLOP = 8;
- private static final long TAP_TIMEOUT = ViewConfiguration.getTapTimeout();
+ private static final long TIMEOUT = ViewConfiguration.getLongPressTimeout();
private static final Rect sHwArea = new Rect(100, 200, 500, 500);
private HandwritingInitiator mHandwritingInitiator;
@@ -177,7 +177,7 @@
}
@Test
- public void onTouchEvent_notStartHandwriting_when_stylusMove_afterTapTimeOut() {
+ public void onTouchEvent_notStartHandwriting_when_stylusMove_afterTimeOut() {
mHandwritingInitiator.onInputConnectionCreated(mTestView);
final int x1 = 10;
final int y1 = 10;
@@ -187,7 +187,7 @@
final int x2 = x1 + TOUCH_SLOP * 2;
final int y2 = y1;
- final long time2 = time1 + TAP_TIMEOUT + 10L;
+ final long time2 = time1 + TIMEOUT + 10L;
MotionEvent stylusEvent2 = createStylusEvent(ACTION_MOVE, x2, y2, time2);
mHandwritingInitiator.onTouchEvent(stylusEvent2);
diff --git a/core/tests/coretests/src/android/window/BackNavigationTest.java b/core/tests/coretests/src/android/window/BackNavigationTest.java
index 8fa48ef..94a149b 100644
--- a/core/tests/coretests/src/android/window/BackNavigationTest.java
+++ b/core/tests/coretests/src/android/window/BackNavigationTest.java
@@ -111,12 +111,12 @@
CountDownLatch backRegisteredLatch = new CountDownLatch(1);
mScenario.onActivity(activity -> {
activity.getOnBackInvokedDispatcher().registerOnBackInvokedCallback(
- new OnBackInvokedCallback() {
+ 0, new OnBackInvokedCallback() {
@Override
public void onBackInvoked() {
backInvokedLatch.countDown();
}
- }, 0
+ }
);
backRegisteredLatch.countDown();
});
diff --git a/core/tests/coretests/src/android/window/WindowOnBackInvokedDispatcherTest.java b/core/tests/coretests/src/android/window/WindowOnBackInvokedDispatcherTest.java
index f8c9944..212f4ed 100644
--- a/core/tests/coretests/src/android/window/WindowOnBackInvokedDispatcherTest.java
+++ b/core/tests/coretests/src/android/window/WindowOnBackInvokedDispatcherTest.java
@@ -77,9 +77,9 @@
ArgumentCaptor.forClass(IOnBackInvokedCallback.class);
mDispatcher.registerOnBackInvokedCallback(
- mCallback1, OnBackInvokedDispatcher.PRIORITY_DEFAULT);
+ OnBackInvokedDispatcher.PRIORITY_DEFAULT, mCallback1);
mDispatcher.registerOnBackInvokedCallback(
- mCallback2, OnBackInvokedDispatcher.PRIORITY_DEFAULT);
+ OnBackInvokedDispatcher.PRIORITY_DEFAULT, mCallback2);
verify(mWindowSession, times(2)).setOnBackInvokedCallback(
Mockito.eq(mWindow),
@@ -102,9 +102,9 @@
ArgumentCaptor.forClass(IOnBackInvokedCallback.class);
mDispatcher.registerOnBackInvokedCallback(
- mCallback1, OnBackInvokedDispatcher.PRIORITY_OVERLAY);
+ OnBackInvokedDispatcher.PRIORITY_OVERLAY, mCallback1);
mDispatcher.registerOnBackInvokedCallback(
- mCallback2, OnBackInvokedDispatcher.PRIORITY_DEFAULT);
+ OnBackInvokedDispatcher.PRIORITY_DEFAULT, mCallback2);
verify(mWindowSession).setOnBackInvokedCallback(
Mockito.eq(mWindow), captor.capture(),
@@ -118,9 +118,9 @@
@Test
public void propagatesTopCallback_withRemoval() throws RemoteException {
mDispatcher.registerOnBackInvokedCallback(
- mCallback1, OnBackInvokedDispatcher.PRIORITY_DEFAULT);
+ OnBackInvokedDispatcher.PRIORITY_DEFAULT, mCallback1);
mDispatcher.registerOnBackInvokedCallback(
- mCallback2, OnBackInvokedDispatcher.PRIORITY_DEFAULT);
+ OnBackInvokedDispatcher.PRIORITY_DEFAULT, mCallback2);
reset(mWindowSession);
mDispatcher.unregisterOnBackInvokedCallback(mCallback1);
@@ -139,16 +139,17 @@
ArgumentCaptor<IOnBackInvokedCallback> captor =
ArgumentCaptor.forClass(IOnBackInvokedCallback.class);
- mDispatcher.registerOnBackInvokedCallback(mCallback1,
- OnBackInvokedDispatcher.PRIORITY_OVERLAY);
+ mDispatcher.registerOnBackInvokedCallback(OnBackInvokedDispatcher.PRIORITY_OVERLAY,
+ mCallback1
+ );
mDispatcher.registerOnBackInvokedCallback(
- mCallback2, OnBackInvokedDispatcher.PRIORITY_DEFAULT);
+ OnBackInvokedDispatcher.PRIORITY_DEFAULT, mCallback2);
mDispatcher.registerOnBackInvokedCallback(
- mCallback1, OnBackInvokedDispatcher.PRIORITY_DEFAULT);
+ OnBackInvokedDispatcher.PRIORITY_DEFAULT, mCallback1);
reset(mWindowSession);
mDispatcher.registerOnBackInvokedCallback(
- mCallback2, OnBackInvokedDispatcher.PRIORITY_OVERLAY);
+ OnBackInvokedDispatcher.PRIORITY_OVERLAY, mCallback2);
verify(mWindowSession).setOnBackInvokedCallback(
Mockito.eq(mWindow),
captor.capture(),
diff --git a/core/tests/coretests/src/com/android/internal/os/BatteryStatsNoteTest.java b/core/tests/coretests/src/com/android/internal/os/BatteryStatsNoteTest.java
index f5cbffb..7ccb9d9 100644
--- a/core/tests/coretests/src/com/android/internal/os/BatteryStatsNoteTest.java
+++ b/core/tests/coretests/src/com/android/internal/os/BatteryStatsNoteTest.java
@@ -17,6 +17,8 @@
package com.android.internal.os;
import static android.os.BatteryStats.NUM_SCREEN_BRIGHTNESS_BINS;
+import static android.os.BatteryStats.POWER_DATA_UNAVAILABLE;
+import static android.os.BatteryStats.RADIO_ACCESS_TECHNOLOGY_COUNT;
import static android.os.BatteryStats.RADIO_ACCESS_TECHNOLOGY_NR;
import static android.os.BatteryStats.STATS_SINCE_CHARGED;
import static android.os.BatteryStats.WAKE_TYPE_PARTIAL;
@@ -24,7 +26,10 @@
import static com.android.internal.os.BatteryStatsImpl.ExternalStatsSync.UPDATE_CPU;
import static com.android.internal.os.BatteryStatsImpl.ExternalStatsSync.UPDATE_DISPLAY;
+import static org.mockito.Mockito.mock;
+
import android.app.ActivityManager;
+import android.app.usage.NetworkStatsManager;
import android.os.BatteryStats;
import android.os.BatteryStats.HistoryItem;
import android.os.BatteryStats.Uid.Sensor;
@@ -34,6 +39,7 @@
import android.telephony.Annotation;
import android.telephony.CellSignalStrength;
import android.telephony.DataConnectionRealTimeInfo;
+import android.telephony.ModemActivityInfo;
import android.telephony.ServiceState;
import android.telephony.TelephonyManager;
import android.util.SparseIntArray;
@@ -48,6 +54,8 @@
import junit.framework.TestCase;
+import org.mockito.Mock;
+
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
@@ -72,6 +80,13 @@
private static final int ISOLATED_UID = UserHandle.getUid(0, ISOLATED_APP_ID);
private static final WorkSource WS = new WorkSource(UID);
+ enum ModemState {
+ SLEEP, IDLE, RECEIVING, TRANSMITTING
+ }
+
+ @Mock
+ NetworkStatsManager mNetworkStatsManager;
+
/**
* Test BatteryStatsImpl.Uid.noteBluetoothScanResultLocked.
*/
@@ -1173,69 +1188,29 @@
}
@SmallTest
- public void testGetPerStateActiveRadioDurationMs() {
+ public void testGetPerStateActiveRadioDurationMs_noModemActivity() {
final MockClock clock = new MockClock(); // holds realtime and uptime in ms
final MockBatteryStatsImpl bi = new MockBatteryStatsImpl(clock);
- final int ratCount = BatteryStats.RADIO_ACCESS_TECHNOLOGY_COUNT;
+ final int ratCount = RADIO_ACCESS_TECHNOLOGY_COUNT;
final int frequencyCount = ServiceState.FREQUENCY_RANGE_MMWAVE + 1;
final int txLevelCount = CellSignalStrength.getNumSignalStrengthLevels();
final long[][][] expectedDurationsMs = new long[ratCount][frequencyCount][txLevelCount];
+ final long[][] expectedRxDurationsMs = new long[ratCount][frequencyCount];
+ final long[][][] expectedTxDurationsMs = new long[ratCount][frequencyCount][txLevelCount];
for (int rat = 0; rat < ratCount; rat++) {
for (int freq = 0; freq < frequencyCount; freq++) {
+ // Should have no RX data without Modem Activity Info
+ expectedRxDurationsMs[rat][freq] = POWER_DATA_UNAVAILABLE;
for (int txLvl = 0; txLvl < txLevelCount; txLvl++) {
expectedDurationsMs[rat][freq][txLvl] = 0;
+ // Should have no TX data without Modem Activity Info
+ expectedTxDurationsMs[rat][freq][txLvl] = POWER_DATA_UNAVAILABLE;
}
}
}
- class ModemAndBatteryState {
- public long currentTimeMs = 100;
- public boolean onBattery = false;
- public boolean modemActive = false;
- @Annotation.NetworkType
- public int currentNetworkDataType = TelephonyManager.NETWORK_TYPE_UNKNOWN;
- @BatteryStats.RadioAccessTechnology
- public int currentRat = BatteryStats.RADIO_ACCESS_TECHNOLOGY_OTHER;
- @ServiceState.FrequencyRange
- public int currentFrequencyRange = ServiceState.FREQUENCY_RANGE_UNKNOWN;
- public SparseIntArray currentSignalStrengths = new SparseIntArray();
-
- void setOnBattery(boolean onBattery) {
- this.onBattery = onBattery;
- bi.updateTimeBasesLocked(onBattery, Display.STATE_OFF, currentTimeMs * 1000,
- currentTimeMs * 1000);
- }
-
- void setModemActive(boolean active) {
- modemActive = active;
- final int state = active ? DataConnectionRealTimeInfo.DC_POWER_STATE_HIGH
- : DataConnectionRealTimeInfo.DC_POWER_STATE_LOW;
- bi.noteMobileRadioPowerStateLocked(state, currentTimeMs * 1000_000L, UID);
- }
-
- void setRatType(@Annotation.NetworkType int dataType,
- @BatteryStats.RadioAccessTechnology int rat) {
- currentNetworkDataType = dataType;
- currentRat = rat;
- bi.notePhoneDataConnectionStateLocked(dataType, true, ServiceState.STATE_IN_SERVICE,
- currentFrequencyRange);
- }
-
- void setFrequencyRange(@ServiceState.FrequencyRange int frequency) {
- currentFrequencyRange = frequency;
- bi.notePhoneDataConnectionStateLocked(currentNetworkDataType, true,
- ServiceState.STATE_IN_SERVICE, frequency);
- }
-
- void setSignalStrength(@BatteryStats.RadioAccessTechnology int rat, int strength) {
- currentSignalStrengths.put(rat, strength);
- final int size = currentSignalStrengths.size();
- final int newestGenSignalStrength = currentSignalStrengths.valueAt(size - 1);
- bi.notePhoneSignalStrengthLocked(newestGenSignalStrength, currentSignalStrengths);
- }
- }
- final ModemAndBatteryState state = new ModemAndBatteryState();
+ final ModemAndBatteryState state = new ModemAndBatteryState(bi, null);
IntConsumer incrementTime = inc -> {
state.currentTimeMs += inc;
@@ -1253,6 +1228,7 @@
expectedDurationsMs[currentRat][currentFrequencyRange][currentSignalStrength] += inc;
};
+
state.setOnBattery(false);
state.setModemActive(false);
state.setRatType(TelephonyManager.NETWORK_TYPE_UNKNOWN,
@@ -1260,95 +1236,367 @@
state.setFrequencyRange(ServiceState.FREQUENCY_RANGE_UNKNOWN);
state.setSignalStrength(BatteryStats.RADIO_ACCESS_TECHNOLOGY_OTHER,
CellSignalStrength.SIGNAL_STRENGTH_NONE_OR_UNKNOWN);
- checkPerStateActiveRadioDurations(expectedDurationsMs, bi, state.currentTimeMs);
+ checkPerStateActiveRadioDurations(expectedDurationsMs, expectedRxDurationsMs,
+ expectedTxDurationsMs, bi, state.currentTimeMs);
// While not on battery, the timers should not increase.
state.setModemActive(true);
incrementTime.accept(100);
- checkPerStateActiveRadioDurations(expectedDurationsMs, bi, state.currentTimeMs);
+ checkPerStateActiveRadioDurations(expectedDurationsMs, expectedRxDurationsMs,
+ expectedTxDurationsMs, bi, state.currentTimeMs);
state.setRatType(TelephonyManager.NETWORK_TYPE_NR, BatteryStats.RADIO_ACCESS_TECHNOLOGY_NR);
incrementTime.accept(200);
- checkPerStateActiveRadioDurations(expectedDurationsMs, bi, state.currentTimeMs);
+ checkPerStateActiveRadioDurations(expectedDurationsMs, expectedRxDurationsMs,
+ expectedTxDurationsMs, bi, state.currentTimeMs);
state.setSignalStrength(BatteryStats.RADIO_ACCESS_TECHNOLOGY_NR,
CellSignalStrength.SIGNAL_STRENGTH_GOOD);
incrementTime.accept(500);
- checkPerStateActiveRadioDurations(expectedDurationsMs, bi, state.currentTimeMs);
+ checkPerStateActiveRadioDurations(expectedDurationsMs, expectedRxDurationsMs,
+ expectedTxDurationsMs, bi, state.currentTimeMs);
state.setFrequencyRange(ServiceState.FREQUENCY_RANGE_MMWAVE);
incrementTime.accept(300);
- checkPerStateActiveRadioDurations(expectedDurationsMs, bi, state.currentTimeMs);
+ checkPerStateActiveRadioDurations(expectedDurationsMs, expectedRxDurationsMs,
+ expectedTxDurationsMs, bi, state.currentTimeMs);
state.setRatType(TelephonyManager.NETWORK_TYPE_LTE,
BatteryStats.RADIO_ACCESS_TECHNOLOGY_LTE);
incrementTime.accept(400);
- checkPerStateActiveRadioDurations(expectedDurationsMs, bi, state.currentTimeMs);
+ checkPerStateActiveRadioDurations(expectedDurationsMs, expectedRxDurationsMs,
+ expectedTxDurationsMs, bi, state.currentTimeMs);
state.setSignalStrength(BatteryStats.RADIO_ACCESS_TECHNOLOGY_LTE,
CellSignalStrength.SIGNAL_STRENGTH_MODERATE);
incrementTime.accept(500);
- checkPerStateActiveRadioDurations(expectedDurationsMs, bi, state.currentTimeMs);
+ checkPerStateActiveRadioDurations(expectedDurationsMs, expectedRxDurationsMs,
+ expectedTxDurationsMs, bi, state.currentTimeMs);
// When set on battery, currently active state (RAT:LTE, Signal Strength:Moderate) should
// start counting up.
state.setOnBattery(true);
incrementTime.accept(600);
- checkPerStateActiveRadioDurations(expectedDurationsMs, bi, state.currentTimeMs);
-
+ checkPerStateActiveRadioDurations(expectedDurationsMs, expectedRxDurationsMs,
+ expectedTxDurationsMs, bi, state.currentTimeMs);
// Changing LTE signal strength should be tracked.
state.setSignalStrength(BatteryStats.RADIO_ACCESS_TECHNOLOGY_LTE,
CellSignalStrength.SIGNAL_STRENGTH_POOR);
incrementTime.accept(700);
- checkPerStateActiveRadioDurations(expectedDurationsMs, bi, state.currentTimeMs);
+ checkPerStateActiveRadioDurations(expectedDurationsMs, expectedRxDurationsMs,
+ expectedTxDurationsMs, bi, state.currentTimeMs);
state.setSignalStrength(BatteryStats.RADIO_ACCESS_TECHNOLOGY_LTE,
CellSignalStrength.SIGNAL_STRENGTH_NONE_OR_UNKNOWN);
incrementTime.accept(800);
- checkPerStateActiveRadioDurations(expectedDurationsMs, bi, state.currentTimeMs);
+ checkPerStateActiveRadioDurations(expectedDurationsMs, expectedRxDurationsMs,
+ expectedTxDurationsMs, bi, state.currentTimeMs);
state.setSignalStrength(BatteryStats.RADIO_ACCESS_TECHNOLOGY_LTE,
CellSignalStrength.SIGNAL_STRENGTH_GOOD);
incrementTime.accept(900);
- checkPerStateActiveRadioDurations(expectedDurationsMs, bi, state.currentTimeMs);
+ checkPerStateActiveRadioDurations(expectedDurationsMs, expectedRxDurationsMs,
+ expectedTxDurationsMs, bi, state.currentTimeMs);
state.setSignalStrength(BatteryStats.RADIO_ACCESS_TECHNOLOGY_LTE,
CellSignalStrength.SIGNAL_STRENGTH_GREAT);
incrementTime.accept(1000);
- checkPerStateActiveRadioDurations(expectedDurationsMs, bi, state.currentTimeMs);
+ checkPerStateActiveRadioDurations(expectedDurationsMs, expectedRxDurationsMs,
+ expectedTxDurationsMs, bi, state.currentTimeMs);
// Change in the signal strength of nonactive RAT should not affect anything.
state.setSignalStrength(BatteryStats.RADIO_ACCESS_TECHNOLOGY_OTHER,
CellSignalStrength.SIGNAL_STRENGTH_POOR);
incrementTime.accept(1100);
- checkPerStateActiveRadioDurations(expectedDurationsMs, bi, state.currentTimeMs);
+ checkPerStateActiveRadioDurations(expectedDurationsMs, expectedRxDurationsMs,
+ expectedTxDurationsMs, bi, state.currentTimeMs);
// Changing to OTHER Rat should start tracking the poor signal strength.
state.setRatType(TelephonyManager.NETWORK_TYPE_CDMA,
BatteryStats.RADIO_ACCESS_TECHNOLOGY_OTHER);
incrementTime.accept(1200);
- checkPerStateActiveRadioDurations(expectedDurationsMs, bi, state.currentTimeMs);
+ checkPerStateActiveRadioDurations(expectedDurationsMs, expectedRxDurationsMs,
+ expectedTxDurationsMs, bi, state.currentTimeMs);
// Noting frequency change should not affect non NR Rat.
state.setFrequencyRange(ServiceState.FREQUENCY_RANGE_HIGH);
incrementTime.accept(1300);
- checkPerStateActiveRadioDurations(expectedDurationsMs, bi, state.currentTimeMs);
+ checkPerStateActiveRadioDurations(expectedDurationsMs, expectedRxDurationsMs,
+ expectedTxDurationsMs, bi, state.currentTimeMs);
// Now the NR Rat, HIGH frequency range, good signal strength should start counting.
state.setRatType(TelephonyManager.NETWORK_TYPE_NR, BatteryStats.RADIO_ACCESS_TECHNOLOGY_NR);
incrementTime.accept(1400);
- checkPerStateActiveRadioDurations(expectedDurationsMs, bi, state.currentTimeMs);
+ checkPerStateActiveRadioDurations(expectedDurationsMs, expectedRxDurationsMs,
+ expectedTxDurationsMs, bi, state.currentTimeMs);
// Noting frequency change should not affect non NR Rat.
state.setFrequencyRange(ServiceState.FREQUENCY_RANGE_LOW);
incrementTime.accept(1500);
- checkPerStateActiveRadioDurations(expectedDurationsMs, bi, state.currentTimeMs);
+ checkPerStateActiveRadioDurations(expectedDurationsMs, expectedRxDurationsMs,
+ expectedTxDurationsMs, bi, state.currentTimeMs);
// Modem no longer active, should not be tracking any more.
state.setModemActive(false);
incrementTime.accept(1500);
- checkPerStateActiveRadioDurations(expectedDurationsMs, bi, state.currentTimeMs);
+ checkPerStateActiveRadioDurations(expectedDurationsMs, expectedRxDurationsMs,
+ expectedTxDurationsMs, bi, state.currentTimeMs);
+ }
+ @SmallTest
+ public void testGetPerStateActiveRadioDurationMs_withModemActivity() {
+ final MockClock clock = new MockClock(); // holds realtime and uptime in ms
+ final MockBatteryStatsImpl bi = new MockBatteryStatsImpl(clock);
+ bi.setPowerProfile(mock(PowerProfile.class));
+ final int ratCount = RADIO_ACCESS_TECHNOLOGY_COUNT;
+ final int frequencyCount = ServiceState.FREQUENCY_RANGE_MMWAVE + 1;
+ final int txLevelCount = CellSignalStrength.getNumSignalStrengthLevels();
+
+ final long[][][] expectedDurationsMs = new long[ratCount][frequencyCount][txLevelCount];
+ final long[][] expectedRxDurationsMs = new long[ratCount][frequencyCount];
+ final long[][][] expectedTxDurationsMs = new long[ratCount][frequencyCount][txLevelCount];
+ for (int rat = 0; rat < ratCount; rat++) {
+ for (int freq = 0; freq < frequencyCount; freq++) {
+ if (rat != RADIO_ACCESS_TECHNOLOGY_NR
+ && freq != ServiceState.FREQUENCY_RANGE_UNKNOWN) {
+ // Only the NR RAT should have per frequency data.
+ expectedRxDurationsMs[rat][freq] = POWER_DATA_UNAVAILABLE;
+ } else {
+ expectedRxDurationsMs[rat][freq] = 0;
+ }
+ expectedRxDurationsMs[rat][freq] = POWER_DATA_UNAVAILABLE;
+
+ for (int txLvl = 0; txLvl < txLevelCount; txLvl++) {
+ expectedDurationsMs[rat][freq][txLvl] = 0;
+
+ if (rat != RADIO_ACCESS_TECHNOLOGY_NR
+ && freq != ServiceState.FREQUENCY_RANGE_UNKNOWN) {
+ // Only the NR RAT should have per frequency data.
+ expectedTxDurationsMs[rat][freq][txLvl] = POWER_DATA_UNAVAILABLE;
+ } else {
+ expectedTxDurationsMs[rat][freq][txLvl] = 0;
+ }
+ expectedTxDurationsMs[rat][freq][txLvl] = POWER_DATA_UNAVAILABLE;
+ }
+ }
+ }
+
+ final ModemActivityInfo mai = new ModemActivityInfo(0L, 0L, 0L, new int[txLevelCount], 0L);
+ final ModemAndBatteryState state = new ModemAndBatteryState(bi, mai);
+
+ IntConsumer incrementTime = inc -> {
+ state.currentTimeMs += inc;
+ clock.realtime = clock.uptime = state.currentTimeMs;
+
+ // If the device is not on battery, no timers should increment.
+ if (!state.onBattery) return;
+ // If the modem is not active, no timers should increment.
+ if (!state.modemActive) return;
+
+ final int currRat = state.currentRat;
+ final int currFreqRange =
+ currRat == RADIO_ACCESS_TECHNOLOGY_NR ? state.currentFrequencyRange : 0;
+ int currSignalStrength = state.currentSignalStrengths.get(currRat);
+
+ expectedDurationsMs[currRat][currFreqRange][currSignalStrength] += inc;
+
+ // Evaluate the HAL provided time in states.
+ switch (state.modemState) {
+ case SLEEP:
+ long sleepMs = state.modemActivityInfo.getSleepTimeMillis();
+ state.modemActivityInfo.setSleepTimeMillis(sleepMs + inc);
+ break;
+ case IDLE:
+ long idleMs = state.modemActivityInfo.getIdleTimeMillis();
+ state.modemActivityInfo.setIdleTimeMillis(idleMs + inc);
+ break;
+ case RECEIVING:
+ long rxMs = state.modemActivityInfo.getReceiveTimeMillis();
+ state.modemActivityInfo.setReceiveTimeMillis(rxMs + inc);
+ expectedRxDurationsMs[currRat][currFreqRange] += inc;
+ break;
+ case TRANSMITTING:
+ int[] txMs = state.modemActivityInfo.getTransmitTimeMillis();
+ txMs[currSignalStrength] += inc;
+ state.modemActivityInfo.setTransmitTimeMillis(txMs);
+ expectedTxDurationsMs[currRat][currFreqRange][currSignalStrength] += inc;
+ break;
+ }
+ };
+
+ state.setOnBattery(false);
+ state.setModemActive(false);
+ state.setRatType(TelephonyManager.NETWORK_TYPE_UNKNOWN,
+ BatteryStats.RADIO_ACCESS_TECHNOLOGY_OTHER);
+ state.setFrequencyRange(ServiceState.FREQUENCY_RANGE_UNKNOWN);
+ state.setSignalStrength(BatteryStats.RADIO_ACCESS_TECHNOLOGY_OTHER,
+ CellSignalStrength.SIGNAL_STRENGTH_NONE_OR_UNKNOWN);
+ checkPerStateActiveRadioDurations(expectedDurationsMs, expectedRxDurationsMs,
+ expectedTxDurationsMs, bi, state.currentTimeMs);
+
+ // While not on battery, the timers should not increase.
+ state.setModemActive(true);
+ incrementTime.accept(100);
+ checkPerStateActiveRadioDurations(expectedDurationsMs, expectedRxDurationsMs,
+ expectedTxDurationsMs, bi, state.currentTimeMs);
+
+ state.setRatType(TelephonyManager.NETWORK_TYPE_NR, BatteryStats.RADIO_ACCESS_TECHNOLOGY_NR);
+ incrementTime.accept(200);
+ checkPerStateActiveRadioDurations(expectedDurationsMs, expectedRxDurationsMs,
+ expectedTxDurationsMs, bi, state.currentTimeMs);
+
+ state.setSignalStrength(BatteryStats.RADIO_ACCESS_TECHNOLOGY_NR,
+ CellSignalStrength.SIGNAL_STRENGTH_GOOD);
+ incrementTime.accept(500);
+ checkPerStateActiveRadioDurations(expectedDurationsMs, expectedRxDurationsMs,
+ expectedTxDurationsMs, bi, state.currentTimeMs);
+
+ state.setFrequencyRange(ServiceState.FREQUENCY_RANGE_MMWAVE);
+ incrementTime.accept(300);
+ checkPerStateActiveRadioDurations(expectedDurationsMs, expectedRxDurationsMs,
+ expectedTxDurationsMs, bi, state.currentTimeMs);
+
+ state.setRatType(TelephonyManager.NETWORK_TYPE_LTE,
+ BatteryStats.RADIO_ACCESS_TECHNOLOGY_LTE);
+ incrementTime.accept(400);
+ checkPerStateActiveRadioDurations(expectedDurationsMs, expectedRxDurationsMs,
+ expectedTxDurationsMs, bi, state.currentTimeMs);
+
+ state.setSignalStrength(BatteryStats.RADIO_ACCESS_TECHNOLOGY_LTE,
+ CellSignalStrength.SIGNAL_STRENGTH_MODERATE);
+ incrementTime.accept(500);
+ checkPerStateActiveRadioDurations(expectedDurationsMs, expectedRxDurationsMs,
+ expectedTxDurationsMs, bi, state.currentTimeMs);
+
+ // Data will now be available.
+ for (int rat = 0; rat < ratCount; rat++) {
+ for (int freq = 0; freq < frequencyCount; freq++) {
+ if (rat == RADIO_ACCESS_TECHNOLOGY_NR
+ || freq == ServiceState.FREQUENCY_RANGE_UNKNOWN) {
+ // Only the NR RAT should have per frequency data.
+ expectedRxDurationsMs[rat][freq] = 0;
+ }
+ for (int txLvl = 0; txLvl < txLevelCount; txLvl++) {
+ if (rat == RADIO_ACCESS_TECHNOLOGY_NR
+ || freq == ServiceState.FREQUENCY_RANGE_UNKNOWN) {
+ // Only the NR RAT should have per frequency data.
+ expectedTxDurationsMs[rat][freq][txLvl] = 0;
+ }
+ }
+ }
+ }
+
+ // When set on battery, currently active state (RAT:LTE, Signal Strength:Moderate) should
+ // start counting up.
+ state.setOnBattery(true);
+ incrementTime.accept(300);
+ state.setModemState(ModemState.RECEIVING);
+ incrementTime.accept(500);
+ state.setModemState(ModemState.TRANSMITTING);
+ incrementTime.accept(600);
+ state.noteModemControllerActivity();
+ checkPerStateActiveRadioDurations(expectedDurationsMs, expectedRxDurationsMs,
+ expectedTxDurationsMs, bi, state.currentTimeMs);
+ // Changing LTE signal strength should be tracked.
+ state.setSignalStrength(BatteryStats.RADIO_ACCESS_TECHNOLOGY_LTE,
+ CellSignalStrength.SIGNAL_STRENGTH_POOR);
+ incrementTime.accept(300);
+ state.setModemState(ModemState.SLEEP);
+ incrementTime.accept(1000);
+ state.setModemState(ModemState.RECEIVING);
+ incrementTime.accept(700);
+ state.noteModemControllerActivity();
+ checkPerStateActiveRadioDurations(expectedDurationsMs, expectedRxDurationsMs,
+ expectedTxDurationsMs, bi, state.currentTimeMs);
+
+ state.setSignalStrength(BatteryStats.RADIO_ACCESS_TECHNOLOGY_LTE,
+ CellSignalStrength.SIGNAL_STRENGTH_NONE_OR_UNKNOWN);
+ incrementTime.accept(800);
+ state.setModemState(ModemState.TRANSMITTING);
+ incrementTime.accept(222);
+ state.setModemState(ModemState.IDLE);
+ incrementTime.accept(111);
+ state.setModemState(ModemState.RECEIVING);
+ incrementTime.accept(7777);
+ state.noteModemControllerActivity();
+ checkPerStateActiveRadioDurations(expectedDurationsMs, expectedRxDurationsMs,
+ expectedTxDurationsMs, bi, state.currentTimeMs);
+
+ state.setSignalStrength(BatteryStats.RADIO_ACCESS_TECHNOLOGY_LTE,
+ CellSignalStrength.SIGNAL_STRENGTH_GOOD);
+ incrementTime.accept(88);
+ state.setModemState(ModemState.TRANSMITTING);
+ incrementTime.accept(900);
+ state.noteModemControllerActivity();
+ checkPerStateActiveRadioDurations(expectedDurationsMs, expectedRxDurationsMs,
+ expectedTxDurationsMs, bi, state.currentTimeMs);
+
+ state.setSignalStrength(BatteryStats.RADIO_ACCESS_TECHNOLOGY_LTE,
+ CellSignalStrength.SIGNAL_STRENGTH_GREAT);
+ incrementTime.accept(123);
+ state.setModemState(ModemState.RECEIVING);
+ incrementTime.accept(333);
+ state.setModemState(ModemState.TRANSMITTING);
+ incrementTime.accept(1000);
+ state.setModemState(ModemState.RECEIVING);
+ incrementTime.accept(555);
+ state.noteModemControllerActivity();
+ checkPerStateActiveRadioDurations(expectedDurationsMs, expectedRxDurationsMs,
+ expectedTxDurationsMs, bi, state.currentTimeMs);
+
+ // Change in the signal strength of nonactive RAT should not affect anything.
+ state.setSignalStrength(BatteryStats.RADIO_ACCESS_TECHNOLOGY_OTHER,
+ CellSignalStrength.SIGNAL_STRENGTH_POOR);
+ incrementTime.accept(631);
+ state.setModemState(ModemState.TRANSMITTING);
+ incrementTime.accept(321);
+ state.setModemState(ModemState.RECEIVING);
+ incrementTime.accept(99);
+ state.noteModemControllerActivity();
+ checkPerStateActiveRadioDurations(expectedDurationsMs, expectedRxDurationsMs,
+ expectedTxDurationsMs, bi, state.currentTimeMs);
+
+ // Changing to OTHER Rat should start tracking the poor signal strength.
+ state.setRatType(TelephonyManager.NETWORK_TYPE_CDMA,
+ BatteryStats.RADIO_ACCESS_TECHNOLOGY_OTHER);
+ incrementTime.accept(1200);
+ state.noteModemControllerActivity();
+ checkPerStateActiveRadioDurations(expectedDurationsMs, expectedRxDurationsMs,
+ expectedTxDurationsMs, bi, state.currentTimeMs);
+
+ // Noting frequency change should not affect non NR Rat.
+ state.setFrequencyRange(ServiceState.FREQUENCY_RANGE_HIGH);
+ incrementTime.accept(444);
+ state.setModemState(ModemState.TRANSMITTING);
+ incrementTime.accept(1300);
+ state.noteModemControllerActivity();
+ checkPerStateActiveRadioDurations(expectedDurationsMs, expectedRxDurationsMs,
+ expectedTxDurationsMs, bi, state.currentTimeMs);
+
+ // Now the NR Rat, HIGH frequency range, good signal strength should start counting.
+ state.setRatType(TelephonyManager.NETWORK_TYPE_NR, BatteryStats.RADIO_ACCESS_TECHNOLOGY_NR);
+ incrementTime.accept(1400);
+ state.noteModemControllerActivity();
+ checkPerStateActiveRadioDurations(expectedDurationsMs, expectedRxDurationsMs,
+ expectedTxDurationsMs, bi, state.currentTimeMs);
+
+ // Frequency changed to low.
+ state.setFrequencyRange(ServiceState.FREQUENCY_RANGE_LOW);
+ incrementTime.accept(852);
+ state.setModemState(ModemState.RECEIVING);
+ incrementTime.accept(157);
+ state.setModemState(ModemState.TRANSMITTING);
+ incrementTime.accept(1500);
+ state.noteModemControllerActivity();
+ checkPerStateActiveRadioDurations(expectedDurationsMs, expectedRxDurationsMs,
+ expectedTxDurationsMs, bi, state.currentTimeMs);
+
+ // Modem no longer active, should not be tracking any more.
+ state.setModemActive(false);
+ incrementTime.accept(1500);
+ state.noteModemControllerActivity();
+ checkPerStateActiveRadioDurations(expectedDurationsMs, expectedRxDurationsMs,
+ expectedTxDurationsMs, bi, state.currentTimeMs);
}
private void setFgState(int uid, boolean fgOn, MockBatteryStatsImpl bi) {
@@ -1426,28 +1674,124 @@
}
private void checkPerStateActiveRadioDurations(long[][][] expectedDurationsMs,
+ long[][] expectedRxDurationsMs, long[][][] expectedTxDurationsMs,
BatteryStatsImpl bi, long currentTimeMs) {
for (int rat = 0; rat < expectedDurationsMs.length; rat++) {
final long[][] expectedRatDurationsMs = expectedDurationsMs[rat];
for (int freq = 0; freq < expectedRatDurationsMs.length; freq++) {
+ final long expectedRxDurationMs = expectedRxDurationsMs[rat][freq];
+
+ // Build a verbose fail message, just in case.
+ final StringBuilder rxFailSb = new StringBuilder();
+ rxFailSb.append("Wrong time in Rx state for RAT:");
+ rxFailSb.append(BatteryStats.RADIO_ACCESS_TECHNOLOGY_NAMES[rat]);
+ rxFailSb.append(", frequency:");
+ rxFailSb.append(ServiceState.frequencyRangeToString(freq));
+ assertEquals(rxFailSb.toString(), expectedRxDurationMs,
+ bi.getActiveRxRadioDurationMs(rat, freq, currentTimeMs));
+
final long[] expectedFreqDurationsMs = expectedRatDurationsMs[freq];
for (int strength = 0; strength < expectedFreqDurationsMs.length; strength++) {
final long expectedSignalStrengthDurationMs = expectedFreqDurationsMs[strength];
+ final long expectedTxDurationMs = expectedTxDurationsMs[rat][freq][strength];
final long actualDurationMs = bi.getActiveRadioDurationMs(rat, freq,
strength, currentTimeMs);
- // Build a verbose fail message, just in case.
- final StringBuilder sb = new StringBuilder();
- sb.append("Wrong time in state for RAT:");
- sb.append(BatteryStats.RADIO_ACCESS_TECHNOLOGY_NAMES[rat]);
- sb.append(", frequency:");
- sb.append(ServiceState.frequencyRangeToString(freq));
- sb.append(", strength:");
- sb.append(strength);
+ final StringBuilder failSb = new StringBuilder();
+ failSb.append("Wrong time in state for RAT:");
+ failSb.append(BatteryStats.RADIO_ACCESS_TECHNOLOGY_NAMES[rat]);
+ failSb.append(", frequency:");
+ failSb.append(ServiceState.frequencyRangeToString(freq));
+ failSb.append(", strength:");
+ failSb.append(strength);
+ assertEquals(failSb.toString(), expectedSignalStrengthDurationMs,
+ actualDurationMs);
- assertEquals(sb.toString(), expectedSignalStrengthDurationMs, actualDurationMs);
+ final StringBuilder txFailSb = new StringBuilder();
+ txFailSb.append("Wrong time in Tx state for RAT:");
+ txFailSb.append(BatteryStats.RADIO_ACCESS_TECHNOLOGY_NAMES[rat]);
+ txFailSb.append(", frequency:");
+ txFailSb.append(ServiceState.frequencyRangeToString(freq));
+ txFailSb.append(", strength:");
+ txFailSb.append(strength);
+ assertEquals(txFailSb.toString(), expectedTxDurationMs,
+ bi.getActiveTxRadioDurationMs(rat, freq, strength, currentTimeMs));
}
}
}
}
+
+ private class ModemAndBatteryState {
+ public long currentTimeMs = 100;
+ public boolean onBattery = false;
+ public boolean modemActive = false;
+ @Annotation.NetworkType
+ public int currentNetworkDataType = TelephonyManager.NETWORK_TYPE_UNKNOWN;
+ @BatteryStats.RadioAccessTechnology
+ public int currentRat = BatteryStats.RADIO_ACCESS_TECHNOLOGY_OTHER;
+ @ServiceState.FrequencyRange
+ public int currentFrequencyRange = ServiceState.FREQUENCY_RANGE_UNKNOWN;
+ public SparseIntArray currentSignalStrengths = new SparseIntArray();
+ public ModemState modemState = ModemState.SLEEP;
+ public ModemActivityInfo modemActivityInfo;
+
+ private final MockBatteryStatsImpl mBsi;
+
+ ModemAndBatteryState(MockBatteryStatsImpl bsi, ModemActivityInfo mai) {
+ mBsi = bsi;
+ modemActivityInfo = mai;
+ }
+
+ void setOnBattery(boolean onBattery) {
+ this.onBattery = onBattery;
+ mBsi.updateTimeBasesLocked(onBattery, Display.STATE_OFF, currentTimeMs * 1000,
+ currentTimeMs * 1000);
+ mBsi.setOnBatteryInternal(onBattery);
+ noteModemControllerActivity();
+ }
+
+ void setModemActive(boolean active) {
+ modemActive = active;
+ final int state = active ? DataConnectionRealTimeInfo.DC_POWER_STATE_HIGH
+ : DataConnectionRealTimeInfo.DC_POWER_STATE_LOW;
+ mBsi.noteMobileRadioPowerStateLocked(state, currentTimeMs * 1000_000L, UID);
+ noteModemControllerActivity();
+ }
+
+ void setRatType(@Annotation.NetworkType int dataType,
+ @BatteryStats.RadioAccessTechnology int rat) {
+ currentNetworkDataType = dataType;
+ currentRat = rat;
+ mBsi.notePhoneDataConnectionStateLocked(dataType, true, ServiceState.STATE_IN_SERVICE,
+ currentFrequencyRange);
+ }
+
+ void setFrequencyRange(@ServiceState.FrequencyRange int frequency) {
+ currentFrequencyRange = frequency;
+ mBsi.notePhoneDataConnectionStateLocked(currentNetworkDataType, true,
+ ServiceState.STATE_IN_SERVICE, frequency);
+ }
+
+ void setSignalStrength(@BatteryStats.RadioAccessTechnology int rat, int strength) {
+ currentSignalStrengths.put(rat, strength);
+ final int size = currentSignalStrengths.size();
+ final int newestGenSignalStrength = currentSignalStrengths.valueAt(size - 1);
+ mBsi.notePhoneSignalStrengthLocked(newestGenSignalStrength, currentSignalStrengths);
+ }
+
+ void setModemState(ModemState state) {
+ modemState = state;
+ }
+
+ void noteModemControllerActivity() {
+ if (modemActivityInfo == null) return;
+ modemActivityInfo.setTimestamp(currentTimeMs);
+ ModemActivityInfo copy = new ModemActivityInfo(modemActivityInfo.getTimestampMillis(),
+ modemActivityInfo.getSleepTimeMillis(), modemActivityInfo.getIdleTimeMillis(),
+ modemActivityInfo.getTransmitTimeMillis().clone(),
+ modemActivityInfo.getReceiveTimeMillis());
+ mBsi.noteModemControllerActivity(copy, POWER_DATA_UNAVAILABLE,
+ currentTimeMs, currentTimeMs, mNetworkStatsManager);
+ }
+ }
}
diff --git a/core/tests/coretests/src/com/android/internal/os/BatteryUsageStatsTest.java b/core/tests/coretests/src/com/android/internal/os/BatteryUsageStatsTest.java
index 5adc9bd..483224c 100644
--- a/core/tests/coretests/src/com/android/internal/os/BatteryUsageStatsTest.java
+++ b/core/tests/coretests/src/com/android/internal/os/BatteryUsageStatsTest.java
@@ -20,6 +20,7 @@
import static android.os.BatteryConsumer.POWER_MODEL_MEASURED_ENERGY;
import static android.os.BatteryConsumer.POWER_MODEL_UNDEFINED;
import static android.os.BatteryConsumer.PROCESS_STATE_BACKGROUND;
+import static android.os.BatteryConsumer.PROCESS_STATE_CACHED;
import static android.os.BatteryConsumer.PROCESS_STATE_FOREGROUND;
import static android.os.BatteryConsumer.PROCESS_STATE_FOREGROUND_SERVICE;
@@ -83,7 +84,7 @@
final Parcel parcel = Parcel.obtain();
parcel.writeParcelable(outBatteryUsageStats, 0);
- assertThat(parcel.dataSize()).isLessThan(7000);
+ assertThat(parcel.dataSize()).isLessThan(8000);
parcel.setDataPosition(0);
@@ -155,10 +156,11 @@
assertThat(dump).contains("cpu(fg): 2333 apps: 1333 duration: 3s 332ms");
assertThat(dump).contains("cpu(bg): 2444 apps: 1444 duration: 4s 442ms");
assertThat(dump).contains("cpu(fgs): 2555 apps: 1555 duration: 5s 552ms");
+ assertThat(dump).contains("cpu(cached): 123 apps: 123 duration: 456ms");
assertThat(dump).contains("FOO: 20200 apps: 10200 duration: 20s 400ms");
- assertThat(dump).contains("UID 271: 1200 fg: 1777 bg: 1888 fgs: 1999 ( screen=300 "
- + "cpu=400 (600ms) cpu:fg=1777 (7s 771ms) cpu:bg=1888 (8s 881ms) "
- + "cpu:fgs=1999 (9s 991ms) FOO=500 )");
+ assertThat(dump).contains("UID 271: 1200 fg: 1777 bg: 1888 fgs: 1999 cached: 123 "
+ + "( screen=300 cpu=400 (600ms) cpu:fg=1777 (7s 771ms) cpu:bg=1888 (8s 881ms) "
+ + "cpu:fgs=1999 (9s 991ms) cpu:cached=123 (456ms) FOO=500 )");
assertThat(dump).contains("User 42: 30.0 ( cpu=10.0 (30ms) FOO=20.0 )");
}
@@ -193,13 +195,15 @@
5321, 7432, 423, BatteryConsumer.POWER_MODEL_POWER_PROFILE, 745,
POWER_MODEL_UNDEFINED,
956, 1167, 1478,
- true, 3554, 3776, 3998, 3554, 15542, 3776, 17762, 3998, 19982);
+ true, 3554, 3776, 3998, 444, 3554, 15542, 3776, 17762, 3998, 19982,
+ 444, 1110);
} else if (uidBatteryConsumer.getUid() == APP_UID2) {
assertUidBatteryConsumer(uidBatteryConsumer, 1332, "bar",
1111, 2222, 333, BatteryConsumer.POWER_MODEL_POWER_PROFILE, 444,
BatteryConsumer.POWER_MODEL_POWER_PROFILE,
555, 666, 777,
- true, 1777, 1888, 1999, 1777, 7771, 1888, 8881, 1999, 9991);
+ true, 1777, 1888, 1999, 321, 1777, 7771, 1888, 8881, 1999, 9991,
+ 321, 654);
} else {
fail("Unexpected UID " + uidBatteryConsumer.getUid());
}
@@ -267,17 +271,17 @@
1000, 2000,
300, BatteryConsumer.POWER_MODEL_POWER_PROFILE, 400,
BatteryConsumer.POWER_MODEL_POWER_PROFILE, 500, 600, 800,
- 1777, 7771, 1888, 8881, 1999, 9991);
+ 1777, 7771, 1888, 8881, 1999, 9991, 123, 456);
addAggregateBatteryConsumer(builder,
BatteryUsageStats.AGGREGATE_BATTERY_CONSUMER_SCOPE_ALL_APPS, 0,
10100, 10200, 10300, 10400,
- 1333, 3331, 1444, 4441, 1555, 5551);
+ 1333, 3331, 1444, 4441, 1555, 5551, 123, 456);
addAggregateBatteryConsumer(builder,
BatteryUsageStats.AGGREGATE_BATTERY_CONSUMER_SCOPE_DEVICE, 30000,
20100, 20200, 20300, 20400,
- 2333, 3332, 2444, 4442, 2555, 5552);
+ 2333, 3332, 2444, 4442, 2555, 5552, 123, 456);
if (includeUserBatteryConsumer) {
builder.getOrCreateUserBatteryConsumerBuilder(USER_ID)
@@ -310,23 +314,23 @@
4321, 5432,
123, BatteryConsumer.POWER_MODEL_POWER_PROFILE, 345, POWER_MODEL_MEASURED_ENERGY,
456, 567, 678,
- 1777, 7771, 1888, 8881, 1999, 9991);
+ 1777, 7771, 1888, 8881, 1999, 9991, 321, 654);
addUidBatteryConsumer(builder, batteryStats, APP_UID2, "bar",
1111, 2222,
333, BatteryConsumer.POWER_MODEL_POWER_PROFILE, 444,
BatteryConsumer.POWER_MODEL_POWER_PROFILE, 555, 666, 777,
- 1777, 7771, 1888, 8881, 1999, 9991);
+ 1777, 7771, 1888, 8881, 1999, 9991, 321, 654);
addAggregateBatteryConsumer(builder,
BatteryUsageStats.AGGREGATE_BATTERY_CONSUMER_SCOPE_ALL_APPS, 0,
10123, 10234, 10345, 10456,
- 4333, 3334, 5444, 4445, 6555, 5556);
+ 4333, 3334, 5444, 4445, 6555, 5556, 321, 654);
addAggregateBatteryConsumer(builder,
BatteryUsageStats.AGGREGATE_BATTERY_CONSUMER_SCOPE_DEVICE, 12345,
20111, 20222, 20333, 20444,
- 7333, 3337, 8444, 4448, 9555, 5559);
+ 7333, 3337, 8444, 4448, 9555, 5559, 123, 456);
return builder;
}
@@ -337,7 +341,7 @@
int screenPowerModel, double cpuPower, int cpuPowerModel, double customComponentPower,
int cpuDuration, int customComponentDuration, double cpuPowerForeground,
int cpuDurationForeground, double cpuPowerBackground, int cpuDurationBackground,
- double cpuPowerFgs, int cpuDurationFgs) {
+ double cpuPowerFgs, int cpuDurationFgs, double cpuPowerCached, long cpuDurationCached) {
final BatteryStatsImpl.Uid batteryStatsUid = batteryStats.getUidStatsLocked(uid);
final UidBatteryConsumer.Builder uidBuilder =
builder.getOrCreateUidBatteryConsumerBuilder(batteryStatsUid);
@@ -365,6 +369,9 @@
final BatteryConsumer.Key cpuFgsKey = uidBuilder.getKey(
BatteryConsumer.POWER_COMPONENT_CPU,
BatteryConsumer.PROCESS_STATE_FOREGROUND_SERVICE);
+ final BatteryConsumer.Key cachedKey = uidBuilder.getKey(
+ BatteryConsumer.POWER_COMPONENT_CPU,
+ BatteryConsumer.PROCESS_STATE_CACHED);
uidBuilder
.setConsumedPower(cpuFgKey, cpuPowerForeground,
BatteryConsumer.POWER_MODEL_POWER_PROFILE)
@@ -374,7 +381,10 @@
.setUsageDurationMillis(cpuBgKey, cpuDurationBackground)
.setConsumedPower(cpuFgsKey, cpuPowerFgs,
BatteryConsumer.POWER_MODEL_POWER_PROFILE)
- .setUsageDurationMillis(cpuFgsKey, cpuDurationFgs);
+ .setUsageDurationMillis(cpuFgsKey, cpuDurationFgs)
+ .setConsumedPower(cachedKey, cpuPowerCached,
+ BatteryConsumer.POWER_MODEL_POWER_PROFILE)
+ .setUsageDurationMillis(cachedKey, cpuDurationCached);
}
}
@@ -382,7 +392,7 @@
double consumedPower, int cpuPower, int customComponentPower, int cpuDuration,
int customComponentDuration, double cpuPowerForeground, long cpuDurationForeground,
double cpuPowerBackground, long cpuDurationBackground, double cpuPowerFgs,
- long cpuDurationFgs) {
+ long cpuDurationFgs, double cpuPowerCached, long cpuDurationCached) {
final AggregateBatteryConsumer.Builder aggBuilder =
builder.getAggregateBatteryConsumerBuilder(scope)
.setConsumedPower(consumedPower)
@@ -406,6 +416,9 @@
final BatteryConsumer.Key cpuFgsKey = aggBuilder.getKey(
BatteryConsumer.POWER_COMPONENT_CPU,
BatteryConsumer.PROCESS_STATE_FOREGROUND_SERVICE);
+ final BatteryConsumer.Key cpuCachedKey = aggBuilder.getKey(
+ BatteryConsumer.POWER_COMPONENT_CPU,
+ BatteryConsumer.PROCESS_STATE_CACHED);
aggBuilder
.setConsumedPower(cpuFgKey, cpuPowerForeground,
BatteryConsumer.POWER_MODEL_POWER_PROFILE)
@@ -415,7 +428,10 @@
.setUsageDurationMillis(cpuBgKey, cpuDurationBackground)
.setConsumedPower(cpuFgsKey, cpuPowerFgs,
BatteryConsumer.POWER_MODEL_POWER_PROFILE)
- .setUsageDurationMillis(cpuFgsKey, cpuDurationFgs);
+ .setUsageDurationMillis(cpuFgsKey, cpuDurationFgs)
+ .setConsumedPower(cpuCachedKey, cpuPowerCached,
+ BatteryConsumer.POWER_MODEL_POWER_PROFILE)
+ .setUsageDurationMillis(cpuCachedKey, cpuDurationCached);
}
}
@@ -432,7 +448,7 @@
1000, 2000, 300, BatteryConsumer.POWER_MODEL_POWER_PROFILE, 400,
BatteryConsumer.POWER_MODEL_POWER_PROFILE,
500, 600, 800,
- true, 1777, 1888, 1999, 1777, 7771, 1888, 8881, 1999, 9991);
+ true, 1777, 1888, 1999, 123, 1777, 7771, 1888, 8881, 1999, 9991, 123, 456);
} else {
fail("Unexpected UID " + uidBatteryConsumer.getUid());
}
@@ -484,8 +500,10 @@
int cpuPowerModel, double customComponentPower, int cpuDuration,
int customComponentDuration, boolean processStateDataIncluded,
double totalPowerForeground, double totalPowerBackground, double totalPowerFgs,
- double cpuPowerForeground, int cpuDurationForeground, double cpuPowerBackground,
- int cpuDurationBackground, double cpuPowerFgs, int cpuDurationFgs) {
+ double totalPowerCached, double cpuPowerForeground, int cpuDurationForeground,
+ double cpuPowerBackground,
+ int cpuDurationBackground, double cpuPowerFgs, int cpuDurationFgs,
+ int cpuPowerCached, int cpuDurationCached) {
assertThat(uidBatteryConsumer.getConsumedPower()).isEqualTo(consumedPower);
assertThat(uidBatteryConsumer.getPackageWithHighestDrain()).isEqualTo(
packageWithHighestDrain);
@@ -525,6 +543,10 @@
new BatteryConsumer.Dimensions(POWER_COMPONENT_ANY,
PROCESS_STATE_FOREGROUND_SERVICE)))
.isEqualTo(totalPowerFgs);
+ assertThat(uidBatteryConsumer.getConsumedPower(
+ new BatteryConsumer.Dimensions(POWER_COMPONENT_ANY,
+ PROCESS_STATE_CACHED)))
+ .isEqualTo(totalPowerCached);
}
final BatteryConsumer.Key cpuFgKey = uidBatteryConsumer.getKey(
@@ -563,6 +585,19 @@
} else {
assertThat(cpuFgsKey).isNotNull();
}
+
+ final BatteryConsumer.Key cachedKey = uidBatteryConsumer.getKey(
+ BatteryConsumer.POWER_COMPONENT_CPU,
+ BatteryConsumer.PROCESS_STATE_CACHED);
+ if (processStateDataIncluded) {
+ assertThat(cachedKey).isNotNull();
+ assertThat(uidBatteryConsumer.getConsumedPower(cachedKey))
+ .isEqualTo(cpuPowerCached);
+ assertThat(uidBatteryConsumer.getUsageDurationMillis(cachedKey))
+ .isEqualTo(cpuDurationCached);
+ } else {
+ assertThat(cpuFgsKey).isNotNull();
+ }
}
private void assertUserBatteryConsumer(UserBatteryConsumer userBatteryConsumer,
diff --git a/core/tests/coretests/src/com/android/internal/os/BluetoothPowerCalculatorTest.java b/core/tests/coretests/src/com/android/internal/os/BluetoothPowerCalculatorTest.java
index 448f666..fdbf071 100644
--- a/core/tests/coretests/src/com/android/internal/os/BluetoothPowerCalculatorTest.java
+++ b/core/tests/coretests/src/com/android/internal/os/BluetoothPowerCalculatorTest.java
@@ -145,10 +145,14 @@
final BatteryConsumer.Key fgs = uidConsumer.getKey(
BatteryConsumer.POWER_COMPONENT_BLUETOOTH,
BatteryConsumer.PROCESS_STATE_FOREGROUND_SERVICE);
+ final BatteryConsumer.Key cached = uidConsumer.getKey(
+ BatteryConsumer.POWER_COMPONENT_BLUETOOTH,
+ BatteryConsumer.PROCESS_STATE_CACHED);
assertThat(uidConsumer.getConsumedPower(foreground)).isWithin(PRECISION).of(0.081);
assertThat(uidConsumer.getConsumedPower(background)).isWithin(PRECISION).of(0.0416666);
assertThat(uidConsumer.getConsumedPower(fgs)).isWithin(PRECISION).of(0);
+ assertThat(uidConsumer.getConsumedPower(cached)).isWithin(PRECISION).of(0);
}
@Test
@@ -261,10 +265,14 @@
final BatteryConsumer.Key fgs = uidConsumer.getKey(
BatteryConsumer.POWER_COMPONENT_BLUETOOTH,
BatteryConsumer.PROCESS_STATE_FOREGROUND_SERVICE);
+ final BatteryConsumer.Key cached = uidConsumer.getKey(
+ BatteryConsumer.POWER_COMPONENT_BLUETOOTH,
+ BatteryConsumer.PROCESS_STATE_CACHED);
assertThat(uidConsumer.getConsumedPower(foreground)).isWithin(PRECISION).of(0.4965352);
assertThat(uidConsumer.getConsumedPower(background)).isWithin(PRECISION).of(0.3255208);
assertThat(uidConsumer.getConsumedPower(fgs)).isWithin(PRECISION).of(0);
+ assertThat(uidConsumer.getConsumedPower(cached)).isWithin(PRECISION).of(0);
}
diff --git a/core/tests/coretests/src/com/android/internal/os/LooperStatsTest.java b/core/tests/coretests/src/com/android/internal/os/LooperStatsTest.java
index b89e8bc..625f52a 100644
--- a/core/tests/coretests/src/com/android/internal/os/LooperStatsTest.java
+++ b/core/tests/coretests/src/com/android/internal/os/LooperStatsTest.java
@@ -232,7 +232,7 @@
assertThat(entry3.handlerClassName).isEqualTo(
"com.android.internal.os.LooperStatsTest$TestHandlerSecond");
assertThat(entry3.messageName).startsWith(
- "com.android.internal.os.LooperStatsTest$$ExternalSyntheticLambda4");
+ "com.android.internal.os.LooperStatsTest$$ExternalSyntheticLambda");
assertThat(entry3.messageCount).isEqualTo(1);
assertThat(entry3.recordedMessageCount).isEqualTo(1);
assertThat(entry3.exceptionCount).isEqualTo(0);
diff --git a/core/tests/mockingcoretests/src/android/util/TimingsTraceLogTest.java b/core/tests/mockingcoretests/src/android/util/TimingsTraceLogTest.java
index 5dc44d2..8de9196 100644
--- a/core/tests/mockingcoretests/src/android/util/TimingsTraceLogTest.java
+++ b/core/tests/mockingcoretests/src/android/util/TimingsTraceLogTest.java
@@ -123,7 +123,7 @@
public void testLogDuration() throws Exception {
TimingsTraceLog log = new TimingsTraceLog(TAG, TRACE_TAG_APP, 10);
log.logDuration("logro", 42);
- verify((MockedVoidMethod) () -> Slog.d(eq(TAG), contains("logro took to complete: 42ms")));
+ verify((MockedVoidMethod) () -> Slog.v(eq(TAG), contains("logro took to complete: 42ms")));
}
@Test
@@ -134,7 +134,7 @@
verify((MockedVoidMethod) () -> Trace.traceBegin(TRACE_TAG_APP, "test"));
verify((MockedVoidMethod) () -> Trace.traceEnd(TRACE_TAG_APP));
- verify((MockedVoidMethod) () -> Slog.d(eq(TAG), matches("test took to complete: \\dms")));
+ verify((MockedVoidMethod) () -> Slog.v(eq(TAG), matches("test took to complete: \\dms")));
}
@Test
@@ -149,8 +149,8 @@
verify((MockedVoidMethod) () -> Trace.traceBegin(TRACE_TAG_APP, "L2"));
verify((MockedVoidMethod) () -> Trace.traceEnd(TRACE_TAG_APP), times(2)); // L1 and L2
- verify((MockedVoidMethod) () -> Slog.d(eq(TAG), matches("L2 took to complete: \\d+ms")));
- verify((MockedVoidMethod) () -> Slog.d(eq(TAG), matches("L1 took to complete: \\d+ms")));
+ verify((MockedVoidMethod) () -> Slog.v(eq(TAG), matches("L2 took to complete: \\d+ms")));
+ verify((MockedVoidMethod) () -> Slog.v(eq(TAG), matches("L1 took to complete: \\d+ms")));
}
@Test
@@ -170,9 +170,9 @@
verify((MockedVoidMethod) () -> Trace.traceBegin(TRACE_TAG_APP, "L3"));
verify((MockedVoidMethod) () -> Trace.traceEnd(TRACE_TAG_APP), times(3));
- verify((MockedVoidMethod) () -> Slog.d(eq(TAG), matches("L2 took to complete: \\d+ms")));
- verify((MockedVoidMethod) () -> Slog.d(eq(TAG), matches("L1 took to complete: \\d+ms")));
- verify((MockedVoidMethod) () -> Slog.d(eq(TAG), matches("L3 took to complete: \\d+ms")),
+ verify((MockedVoidMethod) () -> Slog.v(eq(TAG), matches("L2 took to complete: \\d+ms")));
+ verify((MockedVoidMethod) () -> Slog.v(eq(TAG), matches("L1 took to complete: \\d+ms")));
+ verify((MockedVoidMethod) () -> Slog.v(eq(TAG), matches("L3 took to complete: \\d+ms")),
never());
verify((MockedVoidMethod) () -> Slog.w(TAG, "not tracing duration of 'L3' "
diff --git a/data/etc/Android.bp b/data/etc/Android.bp
index 2a82d8e..df51871 100644
--- a/data/etc/Android.bp
+++ b/data/etc/Android.bp
@@ -71,14 +71,6 @@
}
prebuilt_etc {
- name: "privapp_whitelist_com.android.cellbroadcastreceiver",
- system_ext_specific: true,
- sub_dir: "permissions",
- src: "com.android.cellbroadcastreceiver.xml",
- filename_from_src: true,
-}
-
-prebuilt_etc {
name: "privapp_whitelist_com.android.contacts",
product_specific: true,
sub_dir: "permissions",
diff --git a/data/etc/com.android.cellbroadcastreceiver.xml b/data/etc/com.android.cellbroadcastreceiver.xml
deleted file mode 100644
index bc62bbc..0000000
--- a/data/etc/com.android.cellbroadcastreceiver.xml
+++ /dev/null
@@ -1,29 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
- ~ Copyright (C) 2020 The Android Open Source Project
- ~
- ~ Licensed under the Apache License, Version 2.0 (the "License");
- ~ you may not use this file except in compliance with the License.
- ~ You may obtain a copy of the License at
- ~
- ~ http://www.apache.org/licenses/LICENSE-2.0
- ~
- ~ Unless required by applicable law or agreed to in writing, software
- ~ distributed under the License is distributed on an "AS IS" BASIS,
- ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- ~ See the License for the specific language governing permissions and
- ~ limitations under the License
- -->
-<permissions>
- <privapp-permissions package="com.android.cellbroadcastreceiver">
- <permission name="android.permission.BROADCAST_CLOSE_SYSTEM_DIALOGS"/>
- <permission name="android.permission.INTERACT_ACROSS_USERS"/>
- <permission name="android.permission.MANAGE_USERS"/>
- <permission name="android.permission.STATUS_BAR"/>
- <permission name="android.permission.MODIFY_PHONE_STATE"/>
- <permission name="android.permission.MODIFY_CELL_BROADCASTS"/>
- <permission name="android.permission.READ_PRIVILEGED_PHONE_STATE"/>
- <permission name="android.permission.RECEIVE_EMERGENCY_BROADCAST"/>
- <permission name="android.permission.START_ACTIVITIES_FROM_BACKGROUND"/>
- </privapp-permissions>
-</permissions>
diff --git a/data/etc/com.android.systemui.xml b/data/etc/com.android.systemui.xml
index d1873a0..2d1db71 100644
--- a/data/etc/com.android.systemui.xml
+++ b/data/etc/com.android.systemui.xml
@@ -76,5 +76,8 @@
<permission name="android.permission.FORCE_STOP_PACKAGES" />
<permission name="android.permission.ACCESS_FPS_COUNTER" />
<permission name="android.permission.CHANGE_CONFIGURATION" />
+ <permission name="android.permission.LOG_COMPAT_CHANGE" />
+ <permission name="android.permission.READ_COMPAT_CHANGE_CONFIG" />
+ <permission name="android.permission.READ_DEVICE_CONFIG" />
</privapp-permissions>
</permissions>
diff --git a/data/etc/privapp-permissions-platform.xml b/data/etc/privapp-permissions-platform.xml
index c3b0017..a973078 100644
--- a/data/etc/privapp-permissions-platform.xml
+++ b/data/etc/privapp-permissions-platform.xml
@@ -38,24 +38,6 @@
<permission name="android.permission.CRYPT_KEEPER"/>
</privapp-permissions>
- <privapp-permissions package="com.android.cellbroadcastreceiver.module">
- <permission name="android.permission.BROADCAST_CLOSE_SYSTEM_DIALOGS"/>
- <permission name="android.permission.INTERACT_ACROSS_USERS"/>
- <permission name="android.permission.MANAGE_USERS"/>
- <permission name="android.permission.STATUS_BAR"/>
- <permission name="android.permission.MODIFY_PHONE_STATE"/>
- <permission name="android.permission.MODIFY_CELL_BROADCASTS"/>
- <permission name="android.permission.READ_PRIVILEGED_PHONE_STATE"/>
- <permission name="android.permission.RECEIVE_EMERGENCY_BROADCAST"/>
- <permission name="android.permission.START_ACTIVITIES_FROM_BACKGROUND"/>
- </privapp-permissions>
-
- <privapp-permissions package="com.android.cellbroadcastservice">
- <permission name="android.permission.MODIFY_PHONE_STATE"/>
- <permission name="android.permission.READ_PRIVILEGED_PHONE_STATE"/>
- <permission name="android.permission.RECEIVE_EMERGENCY_BROADCAST"/>
- </privapp-permissions>
-
<privapp-permissions package="com.android.externalstorage">
<permission name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS"/>
<permission name="android.permission.WRITE_MEDIA_STORAGE"/>
@@ -275,6 +257,8 @@
<!-- Needed for test only -->
<permission name="android.permission.BATTERY_PREDICTION"/>
<permission name="android.permission.BATTERY_STATS"/>
+ <!-- BLUETOOTH_PRIVILEGED is needed for test only -->
+ <permission name="android.permission.BLUETOOTH_PRIVILEGED"/>
<permission name="android.permission.BIND_APPWIDGET"/>
<permission name="android.permission.CHANGE_APP_IDLE_STATE"/>
<permission name="android.permission.CHANGE_COMPONENT_ENABLED_STATE"/>
@@ -452,6 +436,7 @@
<permission name="android.permission.WIFI_ACCESS_COEX_UNSAFE_CHANNELS" />
<permission name="android.permission.WIFI_UPDATE_COEX_UNSAFE_CHANNELS" />
<permission name="android.permission.NEARBY_WIFI_DEVICES" />
+ <permission name="android.permission.MANAGE_WIFI_INTERFACES" />
<permission name="android.permission.OVERRIDE_WIFI_CONFIG" />
<!-- Permission needed for CTS test - ConcurrencyTest#testP2pExternalApprover
P2P external approver API sets require MANAGE_WIFI_NETWORK_SELECTION permission. -->
diff --git a/data/etc/services.core.protolog.json b/data/etc/services.core.protolog.json
index df2b2a3..4449c48 100644
--- a/data/etc/services.core.protolog.json
+++ b/data/etc/services.core.protolog.json
@@ -1309,6 +1309,12 @@
"group": "WM_DEBUG_STATES",
"at": "com\/android\/server\/wm\/ActivityRecord.java"
},
+ "-711194343": {
+ "message": "Setting Activity.mLauncherTaskBehind to false. Activity=%s",
+ "level": "DEBUG",
+ "group": "WM_DEBUG_BACK_PREVIEW",
+ "at": "com\/android\/server\/wm\/BackNavigationController.java"
+ },
"-706481945": {
"message": "TaskFragment parent info changed name=%s parentTaskId=%d",
"level": "VERBOSE",
@@ -2251,6 +2257,12 @@
"group": "WM_DEBUG_WINDOW_TRANSITIONS",
"at": "com\/android\/server\/wm\/TransitionController.java"
},
+ "264036181": {
+ "message": "Unable to retrieve task to start recording for display %d",
+ "level": "VERBOSE",
+ "group": "WM_DEBUG_CONTENT_RECORDING",
+ "at": "com\/android\/server\/wm\/ContentRecorder.java"
+ },
"269576220": {
"message": "Resuming rotation after drag",
"level": "DEBUG",
@@ -2587,6 +2599,12 @@
"group": "WM_DEBUG_APP_TRANSITIONS",
"at": "com\/android\/server\/wm\/WindowState.java"
},
+ "599897753": {
+ "message": "Previous Activity is %s. Back type is %s",
+ "level": "DEBUG",
+ "group": "WM_DEBUG_BACK_PREVIEW",
+ "at": "com\/android\/server\/wm\/BackNavigationController.java"
+ },
"600140673": {
"message": "checkBootAnimationComplete: Waiting for anim complete",
"level": "INFO",
@@ -2671,12 +2689,6 @@
"group": "WM_ERROR",
"at": "com\/android\/server\/wm\/WindowManagerService.java"
},
- "664667685": {
- "message": "Activity %s: enableOnBackInvokedCallback=false. Returning null BackNavigationInfo.",
- "level": "DEBUG",
- "group": "WM_DEBUG_BACK_PREVIEW",
- "at": "com\/android\/server\/wm\/BackNavigationController.java"
- },
"665256544": {
"message": "All windows drawn!",
"level": "DEBUG",
@@ -2755,6 +2767,12 @@
"group": "WM_DEBUG_WALLPAPER",
"at": "com\/android\/server\/wm\/WallpaperWindowToken.java"
},
+ "736003885": {
+ "message": "Unable to retrieve the task token to start recording for display %d",
+ "level": "VERBOSE",
+ "group": "WM_DEBUG_CONTENT_RECORDING",
+ "at": "com\/android\/server\/wm\/ContentRecorder.java"
+ },
"736692676": {
"message": "Config is relaunching %s",
"level": "VERBOSE",
@@ -2785,6 +2803,12 @@
"group": "WM_DEBUG_RECENTS_ANIMATIONS",
"at": "com\/android\/server\/wm\/RecentsAnimation.java"
},
+ "778774915": {
+ "message": "Unable to record task since feature is disabled %d",
+ "level": "VERBOSE",
+ "group": "WM_DEBUG_CONTENT_RECORDING",
+ "at": "com\/android\/server\/wm\/ContentRecorder.java"
+ },
"781471998": {
"message": "moveWindowTokenToDisplay: Cannot move to the original display for token: %s",
"level": "WARN",
@@ -2887,6 +2911,12 @@
"group": "WM_DEBUG_STATES",
"at": "com\/android\/server\/wm\/TaskFragment.java"
},
+ "948208142": {
+ "message": "Setting Activity.mLauncherTaskBehind to true. Activity=%s",
+ "level": "DEBUG",
+ "group": "WM_DEBUG_BACK_PREVIEW",
+ "at": "com\/android\/server\/wm\/BackNavigationController.java"
+ },
"950074526": {
"message": "setLockTaskMode: Can't lock due to auth",
"level": "WARN",
@@ -3103,6 +3133,12 @@
"group": "WM_DEBUG_APP_TRANSITIONS",
"at": "com\/android\/server\/wm\/DisplayContent.java"
},
+ "1172542963": {
+ "message": "onBackNavigationDone backType=%s, task=%s, prevTaskTopActivity=%s",
+ "level": "DEBUG",
+ "group": "WM_DEBUG_BACK_PREVIEW",
+ "at": "com\/android\/server\/wm\/BackNavigationController.java"
+ },
"1178653181": {
"message": "Old wallpaper still the target.",
"level": "VERBOSE",
@@ -3415,11 +3451,11 @@
"group": "WM_DEBUG_APP_TRANSITIONS",
"at": "com\/android\/server\/wm\/ActivityRecord.java"
},
- "1554795024": {
- "message": "Previous Activity is %s",
+ "1544805551": {
+ "message": "Skipping app transition animation. task=%s",
"level": "DEBUG",
"group": "WM_DEBUG_BACK_PREVIEW",
- "at": "com\/android\/server\/wm\/BackNavigationController.java"
+ "at": "com\/android\/server\/wm\/Task.java"
},
"1557732761": {
"message": "For Intent %s bringing to top: %s",
diff --git a/graphics/java/android/graphics/Rect.java b/graphics/java/android/graphics/Rect.java
index 7e68bc0..1a522bd 100644
--- a/graphics/java/android/graphics/Rect.java
+++ b/graphics/java/android/graphics/Rect.java
@@ -291,6 +291,14 @@
}
/**
+ * @return {@code true} if the rectangle is valid (left <= right and top <= bottom).
+ * @hide
+ */
+ public boolean isValid() {
+ return left <= right && top <= bottom;
+ }
+
+ /**
* @return the rectangle's width. This does not check for a valid rectangle
* (i.e. left <= right) so the result may be negative.
*/
diff --git a/graphics/java/android/graphics/Typeface.java b/graphics/java/android/graphics/Typeface.java
index 61f7fac..a2f5301 100644
--- a/graphics/java/android/graphics/Typeface.java
+++ b/graphics/java/android/graphics/Typeface.java
@@ -329,7 +329,7 @@
FontFamily.Builder familyBuilder = null;
for (final FontFileResourceEntry fontFile : filesEntry.getEntries()) {
final Font.Builder fontBuilder = new Font.Builder(mgr, fontFile.getFileName(),
- false /* isAsset */, 0 /* cookie */)
+ false /* isAsset */, AssetManager.COOKIE_UNKNOWN)
.setTtcIndex(fontFile.getTtcIndex())
.setFontVariationSettings(fontFile.getVariationSettings());
if (fontFile.getWeight() != Typeface.RESOLVE_BY_FONT_TABLE) {
diff --git a/graphics/java/android/graphics/fonts/Font.java b/graphics/java/android/graphics/fonts/Font.java
index cd7936d..abd0be9 100644
--- a/graphics/java/android/graphics/fonts/Font.java
+++ b/graphics/java/android/graphics/fonts/Font.java
@@ -179,7 +179,7 @@
*/
public Builder(@NonNull AssetManager am, @NonNull String path) {
try {
- mBuffer = createBuffer(am, path, true /* is asset */, 0 /* cookie */);
+ mBuffer = createBuffer(am, path, true /* is asset */, AssetManager.COOKIE_UNKNOWN);
} catch (IOException e) {
mException = e;
}
diff --git a/graphics/java/android/graphics/text/LineBreakConfig.java b/graphics/java/android/graphics/text/LineBreakConfig.java
index cffdf28..d083e44 100644
--- a/graphics/java/android/graphics/text/LineBreakConfig.java
+++ b/graphics/java/android/graphics/text/LineBreakConfig.java
@@ -26,7 +26,7 @@
/**
* Indicates the strategies can be used when calculating the text wrapping.
*
- * See <a href="https://drafts.csswg.org/css-text/#line-break-property">the line-break property</a>
+ * See <a href="https://www.w3.org/TR/css-text-3/#line-break-property">the line-break property</a>
*/
public final class LineBreakConfig {
@@ -78,21 +78,87 @@
@Retention(RetentionPolicy.SOURCE)
public @interface LineBreakWordStyle {}
- private @LineBreakStyle int mLineBreakStyle = LINE_BREAK_STYLE_NONE;
- private @LineBreakWordStyle int mLineBreakWordStyle = LINE_BREAK_WORD_STYLE_NONE;
+ /**
+ * A builder for creating {@link LineBreakConfig}.
+ */
+ public static final class Builder {
+ // The line break style for the LineBreakConfig.
+ private @LineBreakStyle int mLineBreakStyle = LineBreakConfig.LINE_BREAK_STYLE_NONE;
- public LineBreakConfig() {
+ // The line break word style for the LineBreakConfig.
+ private @LineBreakWordStyle int mLineBreakWordStyle =
+ LineBreakConfig.LINE_BREAK_WORD_STYLE_NONE;
+
+ /**
+ * Builder constructor with line break parameters.
+ */
+ public Builder() {
+ }
+
+ /**
+ * Set the line break style.
+ *
+ * @param lineBreakStyle the new line break style.
+ * @return this Builder
+ */
+ public @NonNull Builder setLineBreakStyle(@LineBreakStyle int lineBreakStyle) {
+ mLineBreakStyle = lineBreakStyle;
+ return this;
+ }
+
+ /**
+ * Set the line break word style.
+ *
+ * @param lineBreakWordStyle the new line break word style.
+ * @return this Builder
+ */
+ public @NonNull Builder setLineBreakWordStyle(@LineBreakWordStyle int lineBreakWordStyle) {
+ mLineBreakWordStyle = lineBreakWordStyle;
+ return this;
+ }
+
+ /**
+ * Build the {@link LineBreakConfig}
+ *
+ * @return the LineBreakConfig instance.
+ */
+ public @NonNull LineBreakConfig build() {
+ return new LineBreakConfig(mLineBreakStyle, mLineBreakWordStyle);
+ }
}
/**
- * Set the line break configuration.
+ * Create the LineBreakConfig instance.
*
- * @param lineBreakConfig the new line break configuration.
+ * @param lineBreakStyle the line break style for text wrapping.
+ * @param lineBreakWordStyle the line break word style for text wrapping.
+ * @return the {@link LineBreakConfig} instance.
+ * @hide
*/
- public void set(@NonNull LineBreakConfig lineBreakConfig) {
- Objects.requireNonNull(lineBreakConfig);
- mLineBreakStyle = lineBreakConfig.getLineBreakStyle();
- mLineBreakWordStyle = lineBreakConfig.getLineBreakWordStyle();
+ public static @NonNull LineBreakConfig getLineBreakConfig(@LineBreakStyle int lineBreakStyle,
+ @LineBreakWordStyle int lineBreakWordStyle) {
+ LineBreakConfig.Builder builder = new LineBreakConfig.Builder();
+ return builder.setLineBreakStyle(lineBreakStyle)
+ .setLineBreakWordStyle(lineBreakWordStyle)
+ .build();
+ }
+
+ /** @hide */
+ public static final LineBreakConfig NONE =
+ new Builder().setLineBreakStyle(LINE_BREAK_STYLE_NONE)
+ .setLineBreakWordStyle(LINE_BREAK_WORD_STYLE_NONE).build();
+
+ private final @LineBreakStyle int mLineBreakStyle;
+ private final @LineBreakWordStyle int mLineBreakWordStyle;
+
+ /**
+ * Constructor with the line break parameters.
+ * Use the {@link LineBreakConfig.Builder} to create the LineBreakConfig instance.
+ */
+ private LineBreakConfig(@LineBreakStyle int lineBreakStyle,
+ @LineBreakWordStyle int lineBreakWordStyle) {
+ mLineBreakStyle = lineBreakStyle;
+ mLineBreakWordStyle = lineBreakWordStyle;
}
/**
@@ -105,15 +171,6 @@
}
/**
- * Set the line break style.
- *
- * @param lineBreakStyle the new line break style.
- */
- public void setLineBreakStyle(@LineBreakStyle int lineBreakStyle) {
- mLineBreakStyle = lineBreakStyle;
- }
-
- /**
* Get the line break word style.
*
* @return The current line break word style to be used for the text wrapping.
@@ -122,15 +179,6 @@
return mLineBreakWordStyle;
}
- /**
- * Set the line break word style.
- *
- * @param lineBreakWordStyle the new line break word style.
- */
- public void setLineBreakWordStyle(@LineBreakWordStyle int lineBreakWordStyle) {
- mLineBreakWordStyle = lineBreakWordStyle;
- }
-
@Override
public boolean equals(Object o) {
if (o == null) return false;
diff --git a/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/SplitController.java b/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/SplitController.java
index 1d2b938..2aa6953 100644
--- a/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/SplitController.java
+++ b/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/SplitController.java
@@ -501,7 +501,7 @@
final TaskFragmentContainer container = getContainerWithActivity(
activity.getActivityToken());
// Don't launch placeholder if the container is occluded.
- if (container != getTopActiveContainer()) {
+ if (container != null && container != getTopActiveContainer()) {
return false;
}
diff --git a/libs/WindowManager/OWNERS b/libs/WindowManager/OWNERS
index 2c61df9..780e4c1 100644
--- a/libs/WindowManager/OWNERS
+++ b/libs/WindowManager/OWNERS
@@ -1,3 +1,6 @@
set noparent
include /services/core/java/com/android/server/wm/OWNERS
+
+# Give submodule owners in shell resource approval
+per-file Shell/res*/*/*.xml = hwwang@google.com, lbill@google.com, madym@google.com
diff --git a/libs/WindowManager/Shell/res/values-af/strings_tv.xml b/libs/WindowManager/Shell/res/values-af/strings_tv.xml
index f552b81..c87bec0 100644
--- a/libs/WindowManager/Shell/res/values-af/strings_tv.xml
+++ b/libs/WindowManager/Shell/res/values-af/strings_tv.xml
@@ -24,4 +24,5 @@
<string name="pip_move" msgid="1544227837964635439">"Skuif PIP"</string>
<string name="pip_expand" msgid="7605396312689038178">"Vou PIP uit"</string>
<string name="pip_collapse" msgid="5732233773786896094">"Vou PIP in"</string>
+ <string name="pip_edu_text" msgid="3672999496647508701">" Dubbeldruk "<annotation icon="home_icon">" TUIS "</annotation>" vir kontroles"</string>
</resources>
diff --git a/libs/WindowManager/Shell/res/values-am/strings_tv.xml b/libs/WindowManager/Shell/res/values-am/strings_tv.xml
index 6b6fe9f..d2335385 100644
--- a/libs/WindowManager/Shell/res/values-am/strings_tv.xml
+++ b/libs/WindowManager/Shell/res/values-am/strings_tv.xml
@@ -24,4 +24,5 @@
<string name="pip_move" msgid="1544227837964635439">"ፒአይፒ ውሰድ"</string>
<string name="pip_expand" msgid="7605396312689038178">"ፒአይፒን ዘርጋ"</string>
<string name="pip_collapse" msgid="5732233773786896094">"ፒአይፒን ሰብስብ"</string>
+ <string name="pip_edu_text" msgid="3672999496647508701">" ለመቆጣጠሪያዎች "<annotation icon="home_icon">"መነሻ"</annotation>"ን ሁለቴ ይጫኑ"</string>
</resources>
diff --git a/libs/WindowManager/Shell/res/values-ar/strings_tv.xml b/libs/WindowManager/Shell/res/values-ar/strings_tv.xml
index a85d7b1..a1ceda5 100644
--- a/libs/WindowManager/Shell/res/values-ar/strings_tv.xml
+++ b/libs/WindowManager/Shell/res/values-ar/strings_tv.xml
@@ -24,4 +24,5 @@
<string name="pip_move" msgid="1544227837964635439">"نقل نافذة داخل النافذة (PIP)"</string>
<string name="pip_expand" msgid="7605396312689038178">"توسيع نافذة داخل النافذة (PIP)"</string>
<string name="pip_collapse" msgid="5732233773786896094">"تصغير نافذة داخل النافذة (PIP)"</string>
+ <string name="pip_edu_text" msgid="3672999496647508701">" انقر مرتين على "<annotation icon="home_icon">" الصفحة الرئيسية "</annotation>" للوصول لعناصر التحكم."</string>
</resources>
diff --git a/libs/WindowManager/Shell/res/values-as/strings_tv.xml b/libs/WindowManager/Shell/res/values-as/strings_tv.xml
index 9e2f550..8d7bd9f 100644
--- a/libs/WindowManager/Shell/res/values-as/strings_tv.xml
+++ b/libs/WindowManager/Shell/res/values-as/strings_tv.xml
@@ -24,4 +24,5 @@
<string name="pip_move" msgid="1544227837964635439">"পিপ স্থানান্তৰ কৰক"</string>
<string name="pip_expand" msgid="7605396312689038178">"পিপ বিস্তাৰ কৰক"</string>
<string name="pip_collapse" msgid="5732233773786896094">"পিপ সংকোচন কৰক"</string>
+ <string name="pip_edu_text" msgid="3672999496647508701">" নিয়ন্ত্ৰণৰ বাবে "<annotation icon="home_icon">" গৃহপৃষ্ঠা "</annotation>" বুটামত দুবাৰ হেঁচক"</string>
</resources>
diff --git a/libs/WindowManager/Shell/res/values-az/strings_tv.xml b/libs/WindowManager/Shell/res/values-az/strings_tv.xml
index 670b02f..87c46fa 100644
--- a/libs/WindowManager/Shell/res/values-az/strings_tv.xml
+++ b/libs/WindowManager/Shell/res/values-az/strings_tv.xml
@@ -24,4 +24,5 @@
<string name="pip_move" msgid="1544227837964635439">"PIP tətbiq edin"</string>
<string name="pip_expand" msgid="7605396312689038178">"PIP-ni genişləndirin"</string>
<string name="pip_collapse" msgid="5732233773786896094">"PIP-ni yığcamlaşdırın"</string>
+ <string name="pip_edu_text" msgid="3672999496647508701">" Nizamlayıcılar üçün "<annotation icon="home_icon">" ƏSAS SƏHİFƏ "</annotation>" süçimini iki dəfə basın"</string>
</resources>
diff --git a/libs/WindowManager/Shell/res/values-b+sr+Latn/strings_tv.xml b/libs/WindowManager/Shell/res/values-b+sr+Latn/strings_tv.xml
index de23d71..c87f306 100644
--- a/libs/WindowManager/Shell/res/values-b+sr+Latn/strings_tv.xml
+++ b/libs/WindowManager/Shell/res/values-b+sr+Latn/strings_tv.xml
@@ -24,4 +24,5 @@
<string name="pip_move" msgid="1544227837964635439">"Premesti sliku u slici"</string>
<string name="pip_expand" msgid="7605396312689038178">"Proširi sliku u slici"</string>
<string name="pip_collapse" msgid="5732233773786896094">"Skupi sliku u slici"</string>
+ <string name="pip_edu_text" msgid="3672999496647508701">" Dvaput pritisnite "<annotation icon="home_icon">" HOME "</annotation>" za kontrole"</string>
</resources>
diff --git a/libs/WindowManager/Shell/res/values-be/strings_tv.xml b/libs/WindowManager/Shell/res/values-be/strings_tv.xml
index 03de88c..3566bc3 100644
--- a/libs/WindowManager/Shell/res/values-be/strings_tv.xml
+++ b/libs/WindowManager/Shell/res/values-be/strings_tv.xml
@@ -24,4 +24,5 @@
<string name="pip_move" msgid="1544227837964635439">"Перамясціць PIP"</string>
<string name="pip_expand" msgid="7605396312689038178">"Разгарнуць відарыс у відарысе"</string>
<string name="pip_collapse" msgid="5732233773786896094">"Згарнуць відарыс у відарысе"</string>
+ <string name="pip_edu_text" msgid="3672999496647508701">" Двойчы націсніце "<annotation icon="home_icon">" ГАЛОЎНЫ ЭКРАН "</annotation>" для пераходу ў налады"</string>
</resources>
diff --git a/libs/WindowManager/Shell/res/values-bg/strings_tv.xml b/libs/WindowManager/Shell/res/values-bg/strings_tv.xml
index 38e1ef8..91049fd 100644
--- a/libs/WindowManager/Shell/res/values-bg/strings_tv.xml
+++ b/libs/WindowManager/Shell/res/values-bg/strings_tv.xml
@@ -24,4 +24,5 @@
<string name="pip_move" msgid="1544227837964635439">"„Картина в картина“: Преместв."</string>
<string name="pip_expand" msgid="7605396312689038178">"Разгъване на прозореца за PIP"</string>
<string name="pip_collapse" msgid="5732233773786896094">"Свиване на прозореца за PIP"</string>
+ <string name="pip_edu_text" msgid="3672999496647508701">" За достъп до контролите натиснете 2 пъти "<annotation icon="home_icon">"НАЧАЛО"</annotation></string>
</resources>
diff --git a/libs/WindowManager/Shell/res/values-bn/strings_tv.xml b/libs/WindowManager/Shell/res/values-bn/strings_tv.xml
index 0b24328..792708d 100644
--- a/libs/WindowManager/Shell/res/values-bn/strings_tv.xml
+++ b/libs/WindowManager/Shell/res/values-bn/strings_tv.xml
@@ -24,4 +24,5 @@
<string name="pip_move" msgid="1544227837964635439">"PIP সরান"</string>
<string name="pip_expand" msgid="7605396312689038178">"PIP বড় করুন"</string>
<string name="pip_collapse" msgid="5732233773786896094">"PIP আড়াল করুন"</string>
+ <string name="pip_edu_text" msgid="3672999496647508701">" কন্ট্রোলের জন্য "<annotation icon="home_icon">" হোম "</annotation>" বোতামে ডবল প্রেস করুন"</string>
</resources>
diff --git a/libs/WindowManager/Shell/res/values-bs/strings_tv.xml b/libs/WindowManager/Shell/res/values-bs/strings_tv.xml
index 63e23c2..b7f0dca 100644
--- a/libs/WindowManager/Shell/res/values-bs/strings_tv.xml
+++ b/libs/WindowManager/Shell/res/values-bs/strings_tv.xml
@@ -24,4 +24,5 @@
<string name="pip_move" msgid="1544227837964635439">"Pokreni sliku u slici"</string>
<string name="pip_expand" msgid="7605396312689038178">"Proširi sliku u slici"</string>
<string name="pip_collapse" msgid="5732233773786896094">"Suzi sliku u slici"</string>
+ <string name="pip_edu_text" msgid="3672999496647508701">" Dvaput pritisnite "<annotation icon="home_icon">" POČETNI EKRAN "</annotation>" za kontrole"</string>
</resources>
diff --git a/libs/WindowManager/Shell/res/values-ca/strings.xml b/libs/WindowManager/Shell/res/values-ca/strings.xml
index 2ec1db4..8a522b3 100644
--- a/libs/WindowManager/Shell/res/values-ca/strings.xml
+++ b/libs/WindowManager/Shell/res/values-ca/strings.xml
@@ -27,7 +27,7 @@
<string name="pip_play" msgid="3496151081459417097">"Reprodueix"</string>
<string name="pip_pause" msgid="690688849510295232">"Posa en pausa"</string>
<string name="pip_skip_to_next" msgid="8403429188794867653">"Ves al següent"</string>
- <string name="pip_skip_to_prev" msgid="7172158111196394092">"Torna a l\'anterior"</string>
+ <string name="pip_skip_to_prev" msgid="7172158111196394092">"Ves a l\'anterior"</string>
<string name="accessibility_action_pip_resize" msgid="4623966104749543182">"Canvia la mida"</string>
<string name="accessibility_action_pip_stash" msgid="4060775037619702641">"Amaga"</string>
<string name="accessibility_action_pip_unstash" msgid="7467499339610437646">"Deixa d\'amagar"</string>
diff --git a/libs/WindowManager/Shell/res/values-ca/strings_tv.xml b/libs/WindowManager/Shell/res/values-ca/strings_tv.xml
index e35390a..1c560c7 100644
--- a/libs/WindowManager/Shell/res/values-ca/strings_tv.xml
+++ b/libs/WindowManager/Shell/res/values-ca/strings_tv.xml
@@ -24,4 +24,5 @@
<string name="pip_move" msgid="1544227837964635439">"Mou pantalla en pantalla"</string>
<string name="pip_expand" msgid="7605396312689038178">"Desplega pantalla en pantalla"</string>
<string name="pip_collapse" msgid="5732233773786896094">"Replega pantalla en pantalla"</string>
+ <string name="pip_edu_text" msgid="3672999496647508701">" Prem dos cops "<annotation icon="home_icon">" INICI "</annotation>" per accedir als controls"</string>
</resources>
diff --git a/libs/WindowManager/Shell/res/values-cs/strings_tv.xml b/libs/WindowManager/Shell/res/values-cs/strings_tv.xml
index 9b38537..9a8cc2b 100644
--- a/libs/WindowManager/Shell/res/values-cs/strings_tv.xml
+++ b/libs/WindowManager/Shell/res/values-cs/strings_tv.xml
@@ -24,4 +24,5 @@
<string name="pip_move" msgid="1544227837964635439">"Přesunout PIP"</string>
<string name="pip_expand" msgid="7605396312689038178">"Rozbalit PIP"</string>
<string name="pip_collapse" msgid="5732233773786896094">"Sbalit PIP"</string>
+ <string name="pip_edu_text" msgid="3672999496647508701">" Ovládací prvky zobrazíte dvojitým stisknutím "<annotation icon="home_icon">"tlačítka plochy"</annotation></string>
</resources>
diff --git a/libs/WindowManager/Shell/res/values-da/strings_tv.xml b/libs/WindowManager/Shell/res/values-da/strings_tv.xml
index 2f3b359..cba660a 100644
--- a/libs/WindowManager/Shell/res/values-da/strings_tv.xml
+++ b/libs/WindowManager/Shell/res/values-da/strings_tv.xml
@@ -24,4 +24,5 @@
<string name="pip_move" msgid="1544227837964635439">"Flyt PIP"</string>
<string name="pip_expand" msgid="7605396312689038178">"Udvid PIP"</string>
<string name="pip_collapse" msgid="5732233773786896094">"Skjul PIP"</string>
+ <string name="pip_edu_text" msgid="3672999496647508701">" Tryk to gange på "<annotation icon="home_icon">" HJEM "</annotation>" for at se indstillinger"</string>
</resources>
diff --git a/libs/WindowManager/Shell/res/values-de/strings_tv.xml b/libs/WindowManager/Shell/res/values-de/strings_tv.xml
index 07fc28d..02a1b66 100644
--- a/libs/WindowManager/Shell/res/values-de/strings_tv.xml
+++ b/libs/WindowManager/Shell/res/values-de/strings_tv.xml
@@ -24,4 +24,5 @@
<string name="pip_move" msgid="1544227837964635439">"BiB verschieben"</string>
<string name="pip_expand" msgid="7605396312689038178">"BiB maximieren"</string>
<string name="pip_collapse" msgid="5732233773786896094">"BiB minimieren"</string>
+ <string name="pip_edu_text" msgid="3672999496647508701">" Für Steuerelemente zweimal "<annotation icon="home_icon">"STARTBILDSCHIRMTASTE"</annotation>" drücken"</string>
</resources>
diff --git a/libs/WindowManager/Shell/res/values-el/strings_tv.xml b/libs/WindowManager/Shell/res/values-el/strings_tv.xml
index 1eba0b7..24cd030 100644
--- a/libs/WindowManager/Shell/res/values-el/strings_tv.xml
+++ b/libs/WindowManager/Shell/res/values-el/strings_tv.xml
@@ -24,4 +24,5 @@
<string name="pip_move" msgid="1544227837964635439">"Μετακίνηση PIP"</string>
<string name="pip_expand" msgid="7605396312689038178">"Ανάπτυξη PIP"</string>
<string name="pip_collapse" msgid="5732233773786896094">"Σύμπτυξη PIP"</string>
+ <string name="pip_edu_text" msgid="3672999496647508701">" Πατήστε δύο φορές "<annotation icon="home_icon">" ΑΡΧΙΚΗ ΟΘΟΝΗ "</annotation>" για στοιχεία ελέγχου"</string>
</resources>
diff --git a/libs/WindowManager/Shell/res/values-en-rAU/strings_tv.xml b/libs/WindowManager/Shell/res/values-en-rAU/strings_tv.xml
index 79a8b95..82257b4 100644
--- a/libs/WindowManager/Shell/res/values-en-rAU/strings_tv.xml
+++ b/libs/WindowManager/Shell/res/values-en-rAU/strings_tv.xml
@@ -24,4 +24,5 @@
<string name="pip_move" msgid="1544227837964635439">"Move PIP"</string>
<string name="pip_expand" msgid="7605396312689038178">"Expand PIP"</string>
<string name="pip_collapse" msgid="5732233773786896094">"Collapse PIP"</string>
+ <string name="pip_edu_text" msgid="3672999496647508701">" Double-press "<annotation icon="home_icon">" HOME "</annotation>" for controls"</string>
</resources>
diff --git a/libs/WindowManager/Shell/res/values-en-rCA/strings_tv.xml b/libs/WindowManager/Shell/res/values-en-rCA/strings_tv.xml
index 79a8b95..82257b4 100644
--- a/libs/WindowManager/Shell/res/values-en-rCA/strings_tv.xml
+++ b/libs/WindowManager/Shell/res/values-en-rCA/strings_tv.xml
@@ -24,4 +24,5 @@
<string name="pip_move" msgid="1544227837964635439">"Move PIP"</string>
<string name="pip_expand" msgid="7605396312689038178">"Expand PIP"</string>
<string name="pip_collapse" msgid="5732233773786896094">"Collapse PIP"</string>
+ <string name="pip_edu_text" msgid="3672999496647508701">" Double-press "<annotation icon="home_icon">" HOME "</annotation>" for controls"</string>
</resources>
diff --git a/libs/WindowManager/Shell/res/values-en-rGB/strings_tv.xml b/libs/WindowManager/Shell/res/values-en-rGB/strings_tv.xml
index 79a8b95..82257b4 100644
--- a/libs/WindowManager/Shell/res/values-en-rGB/strings_tv.xml
+++ b/libs/WindowManager/Shell/res/values-en-rGB/strings_tv.xml
@@ -24,4 +24,5 @@
<string name="pip_move" msgid="1544227837964635439">"Move PIP"</string>
<string name="pip_expand" msgid="7605396312689038178">"Expand PIP"</string>
<string name="pip_collapse" msgid="5732233773786896094">"Collapse PIP"</string>
+ <string name="pip_edu_text" msgid="3672999496647508701">" Double-press "<annotation icon="home_icon">" HOME "</annotation>" for controls"</string>
</resources>
diff --git a/libs/WindowManager/Shell/res/values-en-rIN/strings_tv.xml b/libs/WindowManager/Shell/res/values-en-rIN/strings_tv.xml
index 79a8b95..82257b4 100644
--- a/libs/WindowManager/Shell/res/values-en-rIN/strings_tv.xml
+++ b/libs/WindowManager/Shell/res/values-en-rIN/strings_tv.xml
@@ -24,4 +24,5 @@
<string name="pip_move" msgid="1544227837964635439">"Move PIP"</string>
<string name="pip_expand" msgid="7605396312689038178">"Expand PIP"</string>
<string name="pip_collapse" msgid="5732233773786896094">"Collapse PIP"</string>
+ <string name="pip_edu_text" msgid="3672999496647508701">" Double-press "<annotation icon="home_icon">" HOME "</annotation>" for controls"</string>
</resources>
diff --git a/libs/WindowManager/Shell/res/values-en-rXC/strings_tv.xml b/libs/WindowManager/Shell/res/values-en-rXC/strings_tv.xml
index 8925f18..a6e494c 100644
--- a/libs/WindowManager/Shell/res/values-en-rXC/strings_tv.xml
+++ b/libs/WindowManager/Shell/res/values-en-rXC/strings_tv.xml
@@ -24,4 +24,5 @@
<string name="pip_move" msgid="1544227837964635439">"Move PIP"</string>
<string name="pip_expand" msgid="7605396312689038178">"Expand PIP"</string>
<string name="pip_collapse" msgid="5732233773786896094">"Collapse PIP"</string>
+ <string name="pip_edu_text" msgid="3672999496647508701">" Double press "<annotation icon="home_icon">" HOME "</annotation>" for controls"</string>
</resources>
diff --git a/libs/WindowManager/Shell/res/values-es-rUS/strings_tv.xml b/libs/WindowManager/Shell/res/values-es-rUS/strings_tv.xml
index 1b1a419..458f6b1 100644
--- a/libs/WindowManager/Shell/res/values-es-rUS/strings_tv.xml
+++ b/libs/WindowManager/Shell/res/values-es-rUS/strings_tv.xml
@@ -24,4 +24,5 @@
<string name="pip_move" msgid="1544227837964635439">"Mover PIP"</string>
<string name="pip_expand" msgid="7605396312689038178">"Maximizar PIP"</string>
<string name="pip_collapse" msgid="5732233773786896094">"Minimizar PIP"</string>
+ <string name="pip_edu_text" msgid="3672999496647508701">" Presiona dos veces "<annotation icon="home_icon">"INICIO"</annotation>" para ver los controles"</string>
</resources>
diff --git a/libs/WindowManager/Shell/res/values-es/strings_tv.xml b/libs/WindowManager/Shell/res/values-es/strings_tv.xml
index 29ff1c6..0a69098 100644
--- a/libs/WindowManager/Shell/res/values-es/strings_tv.xml
+++ b/libs/WindowManager/Shell/res/values-es/strings_tv.xml
@@ -24,4 +24,5 @@
<string name="pip_move" msgid="1544227837964635439">"Mover imagen en imagen"</string>
<string name="pip_expand" msgid="7605396312689038178">"Mostrar imagen en imagen"</string>
<string name="pip_collapse" msgid="5732233773786896094">"Ocultar imagen en imagen"</string>
+ <string name="pip_edu_text" msgid="3672999496647508701">" Pulsa dos veces "<annotation icon="home_icon">"INICIO"</annotation>" para ver los controles"</string>
</resources>
diff --git a/libs/WindowManager/Shell/res/values-et/strings_tv.xml b/libs/WindowManager/Shell/res/values-et/strings_tv.xml
index f528bb2..dc02323 100644
--- a/libs/WindowManager/Shell/res/values-et/strings_tv.xml
+++ b/libs/WindowManager/Shell/res/values-et/strings_tv.xml
@@ -24,4 +24,5 @@
<string name="pip_move" msgid="1544227837964635439">"Teisalda PIP-režiimi"</string>
<string name="pip_expand" msgid="7605396312689038178">"Laienda PIP-akent"</string>
<string name="pip_collapse" msgid="5732233773786896094">"Ahenda PIP-aken"</string>
+ <string name="pip_edu_text" msgid="3672999496647508701">" Nuppude nägemiseks vajutage 2 korda nuppu "<annotation icon="home_icon">"AVAKUVA"</annotation></string>
</resources>
diff --git a/libs/WindowManager/Shell/res/values-eu/strings_tv.xml b/libs/WindowManager/Shell/res/values-eu/strings_tv.xml
index 72f9980..bce06da 100644
--- a/libs/WindowManager/Shell/res/values-eu/strings_tv.xml
+++ b/libs/WindowManager/Shell/res/values-eu/strings_tv.xml
@@ -24,4 +24,5 @@
<string name="pip_move" msgid="1544227837964635439">"Mugitu pantaila txiki gainjarria"</string>
<string name="pip_expand" msgid="7605396312689038178">"Zabaldu pantaila txiki gainjarria"</string>
<string name="pip_collapse" msgid="5732233773786896094">"Tolestu pantaila txiki gainjarria"</string>
+ <string name="pip_edu_text" msgid="3672999496647508701">" Kontrolatzeko aukerak atzitzeko, sakatu birritan "<annotation icon="home_icon">" HASIERA "</annotation></string>
</resources>
diff --git a/libs/WindowManager/Shell/res/values-fa/strings_tv.xml b/libs/WindowManager/Shell/res/values-fa/strings_tv.xml
index 5fa59be..ff9a03c 100644
--- a/libs/WindowManager/Shell/res/values-fa/strings_tv.xml
+++ b/libs/WindowManager/Shell/res/values-fa/strings_tv.xml
@@ -24,4 +24,5 @@
<string name="pip_move" msgid="1544227837964635439">"انتقال PIP (تصویر در تصویر)"</string>
<string name="pip_expand" msgid="7605396312689038178">"گسترده کردن «تصویر در تصویر»"</string>
<string name="pip_collapse" msgid="5732233773786896094">"جمع کردن «تصویر در تصویر»"</string>
+ <string name="pip_edu_text" msgid="3672999496647508701">" برای کنترلها، دکمه "<annotation icon="home_icon">"صفحه اصلی"</annotation>" را دوبار فشار دهید"</string>
</resources>
diff --git a/libs/WindowManager/Shell/res/values-fi/strings_tv.xml b/libs/WindowManager/Shell/res/values-fi/strings_tv.xml
index 217a85c..3e8bf90 100644
--- a/libs/WindowManager/Shell/res/values-fi/strings_tv.xml
+++ b/libs/WindowManager/Shell/res/values-fi/strings_tv.xml
@@ -24,4 +24,5 @@
<string name="pip_move" msgid="1544227837964635439">"Siirrä PIP"</string>
<string name="pip_expand" msgid="7605396312689038178">"Laajenna PIP"</string>
<string name="pip_collapse" msgid="5732233773786896094">"Tiivistä PIP"</string>
+ <string name="pip_edu_text" msgid="3672999496647508701">" Asetukset: paina "<annotation icon="home_icon">"ALOITUSNÄYTTÖPAINIKETTA"</annotation>" kahdesti"</string>
</resources>
diff --git a/libs/WindowManager/Shell/res/values-fr-rCA/strings_tv.xml b/libs/WindowManager/Shell/res/values-fr-rCA/strings_tv.xml
index b6f401f..66e13b8 100644
--- a/libs/WindowManager/Shell/res/values-fr-rCA/strings_tv.xml
+++ b/libs/WindowManager/Shell/res/values-fr-rCA/strings_tv.xml
@@ -24,4 +24,5 @@
<string name="pip_move" msgid="1544227837964635439">"Déplacer l\'image incrustée"</string>
<string name="pip_expand" msgid="7605396312689038178">"Développer l\'image incrustée"</string>
<string name="pip_collapse" msgid="5732233773786896094">"Réduire l\'image incrustée"</string>
+ <string name="pip_edu_text" msgid="3672999496647508701">" Appuyez deux fois sur "<annotation icon="home_icon">" ACCUEIL "</annotation>" pour les commandes"</string>
</resources>
diff --git a/libs/WindowManager/Shell/res/values-fr/strings_tv.xml b/libs/WindowManager/Shell/res/values-fr/strings_tv.xml
index ffa4a22..ed9baf5b6 100644
--- a/libs/WindowManager/Shell/res/values-fr/strings_tv.xml
+++ b/libs/WindowManager/Shell/res/values-fr/strings_tv.xml
@@ -24,4 +24,5 @@
<string name="pip_move" msgid="1544227837964635439">"Déplacer le PIP"</string>
<string name="pip_expand" msgid="7605396312689038178">"Développer la fenêtre PIP"</string>
<string name="pip_collapse" msgid="5732233773786896094">"Réduire la fenêtre PIP"</string>
+ <string name="pip_edu_text" msgid="3672999496647508701">" Menu de commandes : appuyez deux fois sur "<annotation icon="home_icon">"ACCUEIL"</annotation></string>
</resources>
diff --git a/libs/WindowManager/Shell/res/values-gl/strings_tv.xml b/libs/WindowManager/Shell/res/values-gl/strings_tv.xml
index 3a7ed89..a057434 100644
--- a/libs/WindowManager/Shell/res/values-gl/strings_tv.xml
+++ b/libs/WindowManager/Shell/res/values-gl/strings_tv.xml
@@ -24,4 +24,5 @@
<string name="pip_move" msgid="1544227837964635439">"Mover pantalla superposta"</string>
<string name="pip_expand" msgid="7605396312689038178">"Despregar pantalla superposta"</string>
<string name="pip_collapse" msgid="5732233773786896094">"Contraer pantalla superposta"</string>
+ <string name="pip_edu_text" msgid="3672999496647508701">" Preme "<annotation icon="home_icon">"INICIO"</annotation>" dúas veces para acceder aos controis"</string>
</resources>
diff --git a/libs/WindowManager/Shell/res/values-gu/strings_tv.xml b/libs/WindowManager/Shell/res/values-gu/strings_tv.xml
index 7a9bb25..d952591 100644
--- a/libs/WindowManager/Shell/res/values-gu/strings_tv.xml
+++ b/libs/WindowManager/Shell/res/values-gu/strings_tv.xml
@@ -24,4 +24,5 @@
<string name="pip_move" msgid="1544227837964635439">"PIP ખસેડો"</string>
<string name="pip_expand" msgid="7605396312689038178">"PIP મોટી કરો"</string>
<string name="pip_collapse" msgid="5732233773786896094">"PIP નાની કરો"</string>
+ <string name="pip_edu_text" msgid="3672999496647508701">" નિયંત્રણો માટે "<annotation icon="home_icon">" હોમ "</annotation>" બટન પર બે વાર દબાવો"</string>
</resources>
diff --git a/libs/WindowManager/Shell/res/values-hi/strings_tv.xml b/libs/WindowManager/Shell/res/values-hi/strings_tv.xml
index 5776f81..d897ac7 100644
--- a/libs/WindowManager/Shell/res/values-hi/strings_tv.xml
+++ b/libs/WindowManager/Shell/res/values-hi/strings_tv.xml
@@ -24,4 +24,5 @@
<string name="pip_move" msgid="1544227837964635439">"पीआईपी को दूसरी जगह लेकर जाएं"</string>
<string name="pip_expand" msgid="7605396312689038178">"पीआईपी विंडो को बड़ा करें"</string>
<string name="pip_collapse" msgid="5732233773786896094">"पीआईपी विंडो को छोटा करें"</string>
+ <string name="pip_edu_text" msgid="3672999496647508701">" कंट्रोल मेन्यू पर जाने के लिए, "<annotation icon="home_icon">" होम बटन"</annotation>" दो बार दबाएं"</string>
</resources>
diff --git a/libs/WindowManager/Shell/res/values-hr/strings_tv.xml b/libs/WindowManager/Shell/res/values-hr/strings_tv.xml
index e4d6944..8f5f316 100644
--- a/libs/WindowManager/Shell/res/values-hr/strings_tv.xml
+++ b/libs/WindowManager/Shell/res/values-hr/strings_tv.xml
@@ -24,4 +24,5 @@
<string name="pip_move" msgid="1544227837964635439">"Premjesti PIP"</string>
<string name="pip_expand" msgid="7605396312689038178">"Proširi PIP"</string>
<string name="pip_collapse" msgid="5732233773786896094">"Sažmi PIP"</string>
+ <string name="pip_edu_text" msgid="3672999496647508701">" Dvaput pritisnite "<annotation icon="home_icon">"POČETNI ZASLON"</annotation>" za kontrole"</string>
</resources>
diff --git a/libs/WindowManager/Shell/res/values-hu/strings_tv.xml b/libs/WindowManager/Shell/res/values-hu/strings_tv.xml
index 43beeea..fc8d795 100644
--- a/libs/WindowManager/Shell/res/values-hu/strings_tv.xml
+++ b/libs/WindowManager/Shell/res/values-hu/strings_tv.xml
@@ -24,4 +24,5 @@
<string name="pip_move" msgid="1544227837964635439">"PIP áthelyezése"</string>
<string name="pip_expand" msgid="7605396312689038178">"Kép a képben kibontása"</string>
<string name="pip_collapse" msgid="5732233773786896094">"Kép a képben összecsukása"</string>
+ <string name="pip_edu_text" msgid="3672999496647508701">" Vezérlők: "<annotation icon="home_icon">" KEZDŐKÉPERNYŐ "</annotation>" gomb kétszer megnyomva"</string>
</resources>
diff --git a/libs/WindowManager/Shell/res/values-hy/strings_tv.xml b/libs/WindowManager/Shell/res/values-hy/strings_tv.xml
index e439d5c..f5665b8 100644
--- a/libs/WindowManager/Shell/res/values-hy/strings_tv.xml
+++ b/libs/WindowManager/Shell/res/values-hy/strings_tv.xml
@@ -24,4 +24,5 @@
<string name="pip_move" msgid="1544227837964635439">"Տեղափոխել PIP-ը"</string>
<string name="pip_expand" msgid="7605396312689038178">"Ծավալել PIP-ը"</string>
<string name="pip_collapse" msgid="5732233773786896094">"Ծալել PIP-ը"</string>
+ <string name="pip_edu_text" msgid="3672999496647508701">" Կարգավորումների համար կրկնակի սեղմեք "<annotation icon="home_icon">"ԳԼԽԱՎՈՐ ԷԿՐԱՆ"</annotation></string>
</resources>
diff --git a/libs/WindowManager/Shell/res/values-in/strings_tv.xml b/libs/WindowManager/Shell/res/values-in/strings_tv.xml
index 25cb756..a153565 100644
--- a/libs/WindowManager/Shell/res/values-in/strings_tv.xml
+++ b/libs/WindowManager/Shell/res/values-in/strings_tv.xml
@@ -24,4 +24,5 @@
<string name="pip_move" msgid="1544227837964635439">"Pindahkan PIP"</string>
<string name="pip_expand" msgid="7605396312689038178">"Luaskan PIP"</string>
<string name="pip_collapse" msgid="5732233773786896094">"Ciutkan PIP"</string>
+ <string name="pip_edu_text" msgid="3672999496647508701">" Tekan dua kali "<annotation icon="home_icon">" HOME "</annotation>" untuk membuka kontrol"</string>
</resources>
diff --git a/libs/WindowManager/Shell/res/values-is/strings_tv.xml b/libs/WindowManager/Shell/res/values-is/strings_tv.xml
index 56b9739..70ca1af 100644
--- a/libs/WindowManager/Shell/res/values-is/strings_tv.xml
+++ b/libs/WindowManager/Shell/res/values-is/strings_tv.xml
@@ -24,4 +24,5 @@
<string name="pip_move" msgid="1544227837964635439">"Færa innfellda mynd"</string>
<string name="pip_expand" msgid="7605396312689038178">"Stækka innfellda mynd"</string>
<string name="pip_collapse" msgid="5732233773786896094">"Minnka innfellda mynd"</string>
+ <string name="pip_edu_text" msgid="3672999496647508701">" Ýttu tvisvar á "<annotation icon="home_icon">" HEIM "</annotation>" til að opna stillingar"</string>
</resources>
diff --git a/libs/WindowManager/Shell/res/values-it/strings_tv.xml b/libs/WindowManager/Shell/res/values-it/strings_tv.xml
index 735c5cd..cda6275 100644
--- a/libs/WindowManager/Shell/res/values-it/strings_tv.xml
+++ b/libs/WindowManager/Shell/res/values-it/strings_tv.xml
@@ -24,4 +24,5 @@
<string name="pip_move" msgid="1544227837964635439">"Sposta PIP"</string>
<string name="pip_expand" msgid="7605396312689038178">"Espandi PIP"</string>
<string name="pip_collapse" msgid="5732233773786896094">"Comprimi PIP"</string>
+ <string name="pip_edu_text" msgid="3672999496647508701">" Premi due volte "<annotation icon="home_icon">" HOME "</annotation>" per aprire i controlli"</string>
</resources>
diff --git a/libs/WindowManager/Shell/res/values-iw/strings_tv.xml b/libs/WindowManager/Shell/res/values-iw/strings_tv.xml
index e4e0bf6..30ce97b 100644
--- a/libs/WindowManager/Shell/res/values-iw/strings_tv.xml
+++ b/libs/WindowManager/Shell/res/values-iw/strings_tv.xml
@@ -24,4 +24,5 @@
<string name="pip_move" msgid="1544227837964635439">"העברת תמונה בתוך תמונה (PIP)"</string>
<string name="pip_expand" msgid="7605396312689038178">"הרחבת חלון תמונה-בתוך-תמונה"</string>
<string name="pip_collapse" msgid="5732233773786896094">"כיווץ של חלון תמונה-בתוך-תמונה"</string>
+ <string name="pip_edu_text" msgid="3672999496647508701">" לחיצה כפולה על "<annotation icon="home_icon">" הלחצן הראשי "</annotation>" תציג את אמצעי הבקרה"</string>
</resources>
diff --git a/libs/WindowManager/Shell/res/values-ja/strings_tv.xml b/libs/WindowManager/Shell/res/values-ja/strings_tv.xml
index c8326a6..e58e7bf6 100644
--- a/libs/WindowManager/Shell/res/values-ja/strings_tv.xml
+++ b/libs/WindowManager/Shell/res/values-ja/strings_tv.xml
@@ -24,4 +24,5 @@
<string name="pip_move" msgid="1544227837964635439">"PIP を移動"</string>
<string name="pip_expand" msgid="7605396312689038178">"PIP を開く"</string>
<string name="pip_collapse" msgid="5732233773786896094">"PIP を閉じる"</string>
+ <string name="pip_edu_text" msgid="3672999496647508701">" コントロールにアクセス: "<annotation icon="home_icon">" ホーム "</annotation>" を 2 回押します"</string>
</resources>
diff --git a/libs/WindowManager/Shell/res/values-ka/strings_tv.xml b/libs/WindowManager/Shell/res/values-ka/strings_tv.xml
index 025e5a5..b096866 100644
--- a/libs/WindowManager/Shell/res/values-ka/strings_tv.xml
+++ b/libs/WindowManager/Shell/res/values-ka/strings_tv.xml
@@ -24,4 +24,5 @@
<string name="pip_move" msgid="1544227837964635439">"PIP გადატანა"</string>
<string name="pip_expand" msgid="7605396312689038178">"PIP-ის გაშლა"</string>
<string name="pip_collapse" msgid="5732233773786896094">"PIP-ის ჩაკეცვა"</string>
+ <string name="pip_edu_text" msgid="3672999496647508701">" მართვის საშუალებებზე წვდომისთვის ორმაგად დააჭირეთ "<annotation icon="home_icon">" მთავარ ღილაკს "</annotation></string>
</resources>
diff --git a/libs/WindowManager/Shell/res/values-kk/strings_tv.xml b/libs/WindowManager/Shell/res/values-kk/strings_tv.xml
index 27afe2e..7bade0d 100644
--- a/libs/WindowManager/Shell/res/values-kk/strings_tv.xml
+++ b/libs/WindowManager/Shell/res/values-kk/strings_tv.xml
@@ -24,4 +24,5 @@
<string name="pip_move" msgid="1544227837964635439">"PIP клипін жылжыту"</string>
<string name="pip_expand" msgid="7605396312689038178">"PIP терезесін жаю"</string>
<string name="pip_collapse" msgid="5732233773786896094">"PIP терезесін жию"</string>
+ <string name="pip_edu_text" msgid="3672999496647508701">" Басқару элементтері: "<annotation icon="home_icon">" НЕГІЗГІ ЭКРАН "</annotation>" түймесін екі рет басыңыз."</string>
</resources>
diff --git a/libs/WindowManager/Shell/res/values-km/strings_tv.xml b/libs/WindowManager/Shell/res/values-km/strings_tv.xml
index 86bad27..721be1f 100644
--- a/libs/WindowManager/Shell/res/values-km/strings_tv.xml
+++ b/libs/WindowManager/Shell/res/values-km/strings_tv.xml
@@ -24,4 +24,5 @@
<string name="pip_move" msgid="1544227837964635439">"ផ្លាស់ទី PIP"</string>
<string name="pip_expand" msgid="7605396312689038178">"ពង្រីក PIP"</string>
<string name="pip_collapse" msgid="5732233773786896094">"បង្រួម PIP"</string>
+ <string name="pip_edu_text" msgid="3672999496647508701">" ចុចពីរដងលើ"<annotation icon="home_icon">"ប៊ូតុងដើម"</annotation>" ដើម្បីបើកផ្ទាំងគ្រប់គ្រង"</string>
</resources>
diff --git a/libs/WindowManager/Shell/res/values-kn/strings_tv.xml b/libs/WindowManager/Shell/res/values-kn/strings_tv.xml
index 3fbfdaa..8310c8a 100644
--- a/libs/WindowManager/Shell/res/values-kn/strings_tv.xml
+++ b/libs/WindowManager/Shell/res/values-kn/strings_tv.xml
@@ -24,4 +24,5 @@
<string name="pip_move" msgid="1544227837964635439">"PIP ಅನ್ನು ಸರಿಸಿ"</string>
<string name="pip_expand" msgid="7605396312689038178">"ಚಿತ್ರದಲ್ಲಿ ಚಿತ್ರವನ್ನು ವಿಸ್ತರಿಸಿ"</string>
<string name="pip_collapse" msgid="5732233773786896094">"ಚಿತ್ರದಲ್ಲಿ ಚಿತ್ರವನ್ನು ಕುಗ್ಗಿಸಿ"</string>
+ <string name="pip_edu_text" msgid="3672999496647508701">" ಕಂಟ್ರೋಲ್ಗಳಿಗಾಗಿ "<annotation icon="home_icon">" ಹೋಮ್ "</annotation>" ಅನ್ನು ಎರಡು ಬಾರಿ ಒತ್ತಿ"</string>
</resources>
diff --git a/libs/WindowManager/Shell/res/values-ko/strings_tv.xml b/libs/WindowManager/Shell/res/values-ko/strings_tv.xml
index fa8c8980..a3e055a 100644
--- a/libs/WindowManager/Shell/res/values-ko/strings_tv.xml
+++ b/libs/WindowManager/Shell/res/values-ko/strings_tv.xml
@@ -24,4 +24,5 @@
<string name="pip_move" msgid="1544227837964635439">"PIP 이동"</string>
<string name="pip_expand" msgid="7605396312689038178">"PIP 펼치기"</string>
<string name="pip_collapse" msgid="5732233773786896094">"PIP 접기"</string>
+ <string name="pip_edu_text" msgid="3672999496647508701">" 제어 메뉴에 액세스하려면 "<annotation icon="home_icon">" 홈 "</annotation>"을 두 번 누르세요."</string>
</resources>
diff --git a/libs/WindowManager/Shell/res/values-ky/strings_tv.xml b/libs/WindowManager/Shell/res/values-ky/strings_tv.xml
index 6e2b810..887ac52 100644
--- a/libs/WindowManager/Shell/res/values-ky/strings_tv.xml
+++ b/libs/WindowManager/Shell/res/values-ky/strings_tv.xml
@@ -24,4 +24,5 @@
<string name="pip_move" msgid="1544227837964635439">"PIP\'ти жылдыруу"</string>
<string name="pip_expand" msgid="7605396312689038178">"PIP\'ти жайып көрсөтүү"</string>
<string name="pip_collapse" msgid="5732233773786896094">"PIP\'ти жыйыштыруу"</string>
+ <string name="pip_edu_text" msgid="3672999496647508701">" Башкаруу элементтерин ачуу үчүн "<annotation icon="home_icon">" БАШКЫ БЕТ "</annotation>" баскычын эки жолу басыңыз"</string>
</resources>
diff --git a/libs/WindowManager/Shell/res/values-lo/strings_tv.xml b/libs/WindowManager/Shell/res/values-lo/strings_tv.xml
index 3d4505d..91c4a03 100644
--- a/libs/WindowManager/Shell/res/values-lo/strings_tv.xml
+++ b/libs/WindowManager/Shell/res/values-lo/strings_tv.xml
@@ -24,4 +24,5 @@
<string name="pip_move" msgid="1544227837964635439">"ຍ້າຍ PIP"</string>
<string name="pip_expand" msgid="7605396312689038178">"ຂະຫຍາຍ PIP"</string>
<string name="pip_collapse" msgid="5732233773786896094">"ຫຍໍ້ PIP ລົງ"</string>
+ <string name="pip_edu_text" msgid="3672999496647508701">" ກົດ "<annotation icon="home_icon">" HOME "</annotation>" ສອງເທື່ອສຳລັບການຄວບຄຸມ"</string>
</resources>
diff --git a/libs/WindowManager/Shell/res/values-lt/strings_tv.xml b/libs/WindowManager/Shell/res/values-lt/strings_tv.xml
index f907055..04265ca 100644
--- a/libs/WindowManager/Shell/res/values-lt/strings_tv.xml
+++ b/libs/WindowManager/Shell/res/values-lt/strings_tv.xml
@@ -24,4 +24,5 @@
<string name="pip_move" msgid="1544227837964635439">"Perkelti PIP"</string>
<string name="pip_expand" msgid="7605396312689038178">"Iškleisti PIP"</string>
<string name="pip_collapse" msgid="5732233773786896094">"Sutraukti PIP"</string>
+ <string name="pip_edu_text" msgid="3672999496647508701">" Jei reikia valdiklių, dukart paspauskite "<annotation icon="home_icon">"PAGRINDINIS"</annotation></string>
</resources>
diff --git a/libs/WindowManager/Shell/res/values-lv/strings_tv.xml b/libs/WindowManager/Shell/res/values-lv/strings_tv.xml
index 04d9409..8c6191e 100644
--- a/libs/WindowManager/Shell/res/values-lv/strings_tv.xml
+++ b/libs/WindowManager/Shell/res/values-lv/strings_tv.xml
@@ -24,4 +24,5 @@
<string name="pip_move" msgid="1544227837964635439">"Pārvietot attēlu attēlā"</string>
<string name="pip_expand" msgid="7605396312689038178">"Izvērst “Attēls attēlā” logu"</string>
<string name="pip_collapse" msgid="5732233773786896094">"Sakļaut “Attēls attēlā” logu"</string>
+ <string name="pip_edu_text" msgid="3672999496647508701">" Atvērt vadīklas: divreiz nospiediet pogu "<annotation icon="home_icon">"SĀKUMS"</annotation></string>
</resources>
diff --git a/libs/WindowManager/Shell/res/values-mk/strings_tv.xml b/libs/WindowManager/Shell/res/values-mk/strings_tv.xml
index e9ee1388..beef1fe 100644
--- a/libs/WindowManager/Shell/res/values-mk/strings_tv.xml
+++ b/libs/WindowManager/Shell/res/values-mk/strings_tv.xml
@@ -24,4 +24,5 @@
<string name="pip_move" msgid="1544227837964635439">"Премести PIP"</string>
<string name="pip_expand" msgid="7605396312689038178">"Прошири ја сликата во слика"</string>
<string name="pip_collapse" msgid="5732233773786896094">"Собери ја сликата во слика"</string>
+ <string name="pip_edu_text" msgid="3672999496647508701">" Притиснете двапати на "<annotation icon="home_icon">" HOME "</annotation>" за контроли"</string>
</resources>
diff --git a/libs/WindowManager/Shell/res/values-ml/strings_tv.xml b/libs/WindowManager/Shell/res/values-ml/strings_tv.xml
index 1ed6b6e..c2a532d 100644
--- a/libs/WindowManager/Shell/res/values-ml/strings_tv.xml
+++ b/libs/WindowManager/Shell/res/values-ml/strings_tv.xml
@@ -24,4 +24,5 @@
<string name="pip_move" msgid="1544227837964635439">"PIP നീക്കുക"</string>
<string name="pip_expand" msgid="7605396312689038178">"PIP വികസിപ്പിക്കുക"</string>
<string name="pip_collapse" msgid="5732233773786896094">"PIP ചുരുക്കുക"</string>
+ <string name="pip_edu_text" msgid="3672999496647508701">" നിയന്ത്രണങ്ങൾക്കായി "<annotation icon="home_icon">" ഹോം "</annotation>" രണ്ട് തവണ അമർത്തുക"</string>
</resources>
diff --git a/libs/WindowManager/Shell/res/values-mn/strings_tv.xml b/libs/WindowManager/Shell/res/values-mn/strings_tv.xml
index d4a6942..bf8c59b 100644
--- a/libs/WindowManager/Shell/res/values-mn/strings_tv.xml
+++ b/libs/WindowManager/Shell/res/values-mn/strings_tv.xml
@@ -24,4 +24,5 @@
<string name="pip_move" msgid="1544227837964635439">"PIP-г зөөх"</string>
<string name="pip_expand" msgid="7605396312689038178">"PIP-г дэлгэх"</string>
<string name="pip_collapse" msgid="5732233773786896094">"PIP-г хураах"</string>
+ <string name="pip_edu_text" msgid="3672999496647508701">" Хяналтад хандах бол "<annotation icon="home_icon">" HOME "</annotation>" дээр хоёр дарна уу"</string>
</resources>
diff --git a/libs/WindowManager/Shell/res/values-mr/strings_tv.xml b/libs/WindowManager/Shell/res/values-mr/strings_tv.xml
index 940f983..5d519b7 100644
--- a/libs/WindowManager/Shell/res/values-mr/strings_tv.xml
+++ b/libs/WindowManager/Shell/res/values-mr/strings_tv.xml
@@ -24,4 +24,5 @@
<string name="pip_move" msgid="1544227837964635439">"PIP हलवा"</string>
<string name="pip_expand" msgid="7605396312689038178">"PIP चा विस्तार करा"</string>
<string name="pip_collapse" msgid="5732233773786896094">"PIP कोलॅप्स करा"</string>
+ <string name="pip_edu_text" msgid="3672999496647508701">" नियंत्रणांसाठी "<annotation icon="home_icon">" होम "</annotation>" दोनदा दाबा"</string>
</resources>
diff --git a/libs/WindowManager/Shell/res/values-ms/strings_tv.xml b/libs/WindowManager/Shell/res/values-ms/strings_tv.xml
index f4b180c..08642c4 100644
--- a/libs/WindowManager/Shell/res/values-ms/strings_tv.xml
+++ b/libs/WindowManager/Shell/res/values-ms/strings_tv.xml
@@ -24,4 +24,5 @@
<string name="pip_move" msgid="1544227837964635439">"Alihkan PIP"</string>
<string name="pip_expand" msgid="7605396312689038178">"Kembangkan PIP"</string>
<string name="pip_collapse" msgid="5732233773786896094">"Kuncupkan PIP"</string>
+ <string name="pip_edu_text" msgid="3672999496647508701">" Tekan dua kali "<annotation icon="home_icon">" LAMAN UTAMA "</annotation>" untuk mengakses kawalan"</string>
</resources>
diff --git a/libs/WindowManager/Shell/res/values-my/strings_tv.xml b/libs/WindowManager/Shell/res/values-my/strings_tv.xml
index 4b2a5ec..e01daee 100644
--- a/libs/WindowManager/Shell/res/values-my/strings_tv.xml
+++ b/libs/WindowManager/Shell/res/values-my/strings_tv.xml
@@ -24,4 +24,5 @@
<string name="pip_move" msgid="1544227837964635439">"PIP ရွှေ့ရန်"</string>
<string name="pip_expand" msgid="7605396312689038178">"PIP ကို ချဲ့ရန်"</string>
<string name="pip_collapse" msgid="5732233773786896094">"PIP ကို လျှော့ပြပါ"</string>
+ <string name="pip_edu_text" msgid="3672999496647508701">" ထိန်းချုပ်မှုအတွက် "<annotation icon="home_icon">" ပင်မခလုတ် "</annotation>" နှစ်ချက်နှိပ်ပါ"</string>
</resources>
diff --git a/libs/WindowManager/Shell/res/values-nb/strings_tv.xml b/libs/WindowManager/Shell/res/values-nb/strings_tv.xml
index be74eeb..65ed0b7 100644
--- a/libs/WindowManager/Shell/res/values-nb/strings_tv.xml
+++ b/libs/WindowManager/Shell/res/values-nb/strings_tv.xml
@@ -24,4 +24,5 @@
<string name="pip_move" msgid="1544227837964635439">"Flytt BIB"</string>
<string name="pip_expand" msgid="7605396312689038178">"Vis BIB"</string>
<string name="pip_collapse" msgid="5732233773786896094">"Skjul BIB"</string>
+ <string name="pip_edu_text" msgid="3672999496647508701">" Dobbelttrykk på "<annotation icon="home_icon">"HJEM"</annotation>" for å åpne kontroller"</string>
</resources>
diff --git a/libs/WindowManager/Shell/res/values-ne/strings_tv.xml b/libs/WindowManager/Shell/res/values-ne/strings_tv.xml
index a36cad6..d33fed6 100644
--- a/libs/WindowManager/Shell/res/values-ne/strings_tv.xml
+++ b/libs/WindowManager/Shell/res/values-ne/strings_tv.xml
@@ -24,4 +24,5 @@
<string name="pip_move" msgid="1544227837964635439">"PIP सार्नुहोस्"</string>
<string name="pip_expand" msgid="7605396312689038178">"PIP विन्डो एक्स्पान्ड गर्नु…"</string>
<string name="pip_collapse" msgid="5732233773786896094">"PIP विन्डो कोल्याप्स गर्नुहोस्"</string>
+ <string name="pip_edu_text" msgid="3672999496647508701">" कन्ट्रोल मेनु खोल्न "<annotation icon="home_icon">" होम "</annotation>" बटन दुई पटक थिच्नुहोस्"</string>
</resources>
diff --git a/libs/WindowManager/Shell/res/values-nl/strings_tv.xml b/libs/WindowManager/Shell/res/values-nl/strings_tv.xml
index eb7ec60..9763c56 100644
--- a/libs/WindowManager/Shell/res/values-nl/strings_tv.xml
+++ b/libs/WindowManager/Shell/res/values-nl/strings_tv.xml
@@ -24,4 +24,5 @@
<string name="pip_move" msgid="1544227837964635439">"SIS verplaatsen"</string>
<string name="pip_expand" msgid="7605396312689038178">"SIS uitvouwen"</string>
<string name="pip_collapse" msgid="5732233773786896094">"SIS samenvouwen"</string>
+ <string name="pip_edu_text" msgid="3672999496647508701">" Druk twee keer op "<annotation icon="home_icon">" HOME "</annotation>" voor bedieningselementen"</string>
</resources>
diff --git a/libs/WindowManager/Shell/res/values-or/strings_tv.xml b/libs/WindowManager/Shell/res/values-or/strings_tv.xml
index e48199f..e034485 100644
--- a/libs/WindowManager/Shell/res/values-or/strings_tv.xml
+++ b/libs/WindowManager/Shell/res/values-or/strings_tv.xml
@@ -24,4 +24,5 @@
<string name="pip_move" msgid="1544227837964635439">"PIPକୁ ମୁଭ କରନ୍ତୁ"</string>
<string name="pip_expand" msgid="7605396312689038178">"PIPକୁ ବିସ୍ତାର କରନ୍ତୁ"</string>
<string name="pip_collapse" msgid="5732233773786896094">"PIPକୁ ସଙ୍କୁଚିତ କରନ୍ତୁ"</string>
+ <string name="pip_edu_text" msgid="3672999496647508701">" ନିୟନ୍ତ୍ରଣଗୁଡ଼ିକ ପାଇଁ "<annotation icon="home_icon">" ହୋମ ବଟନ "</annotation>"କୁ ଦୁଇଥର ଦବାନ୍ତୁ"</string>
</resources>
diff --git a/libs/WindowManager/Shell/res/values-pa/strings_tv.xml b/libs/WindowManager/Shell/res/values-pa/strings_tv.xml
index 891107e..9c01ac3 100644
--- a/libs/WindowManager/Shell/res/values-pa/strings_tv.xml
+++ b/libs/WindowManager/Shell/res/values-pa/strings_tv.xml
@@ -24,4 +24,5 @@
<string name="pip_move" msgid="1544227837964635439">"PIP ਨੂੰ ਲਿਜਾਓ"</string>
<string name="pip_expand" msgid="7605396312689038178">"PIP ਦਾ ਵਿਸਤਾਰ ਕਰੋ"</string>
<string name="pip_collapse" msgid="5732233773786896094">"PIP ਨੂੰ ਸਮੇਟੋ"</string>
+ <string name="pip_edu_text" msgid="3672999496647508701">" ਕੰਟਰੋਲਾਂ ਲਈ "<annotation icon="home_icon">" ਹੋਮ ਬਟਨ "</annotation>" ਨੂੰ ਦੋ ਵਾਰ ਦਬਾਓ"</string>
</resources>
diff --git a/libs/WindowManager/Shell/res/values-pl/strings_tv.xml b/libs/WindowManager/Shell/res/values-pl/strings_tv.xml
index 7b5d08a..b922e2d 100644
--- a/libs/WindowManager/Shell/res/values-pl/strings_tv.xml
+++ b/libs/WindowManager/Shell/res/values-pl/strings_tv.xml
@@ -24,4 +24,5 @@
<string name="pip_move" msgid="1544227837964635439">"Przenieś PIP"</string>
<string name="pip_expand" msgid="7605396312689038178">"Rozwiń PIP"</string>
<string name="pip_collapse" msgid="5732233773786896094">"Zwiń PIP"</string>
+ <string name="pip_edu_text" msgid="3672999496647508701">" Naciśnij dwukrotnie "<annotation icon="home_icon">"EKRAN GŁÓWNY"</annotation>", aby wyświetlić ustawienia"</string>
</resources>
diff --git a/libs/WindowManager/Shell/res/values-pt-rBR/strings_tv.xml b/libs/WindowManager/Shell/res/values-pt-rBR/strings_tv.xml
index b669f16..cc4eb3c 100644
--- a/libs/WindowManager/Shell/res/values-pt-rBR/strings_tv.xml
+++ b/libs/WindowManager/Shell/res/values-pt-rBR/strings_tv.xml
@@ -24,4 +24,5 @@
<string name="pip_move" msgid="1544227837964635439">"Mover picture-in-picture"</string>
<string name="pip_expand" msgid="7605396312689038178">"Abrir picture-in-picture"</string>
<string name="pip_collapse" msgid="5732233773786896094">"Fechar picture-in-picture"</string>
+ <string name="pip_edu_text" msgid="3672999496647508701">" Pressione o botão "<annotation icon="home_icon">"home"</annotation>" duas vezes para acessar os controles"</string>
</resources>
diff --git a/libs/WindowManager/Shell/res/values-pt-rPT/strings_tv.xml b/libs/WindowManager/Shell/res/values-pt-rPT/strings_tv.xml
index 6c1fa59..c4ae78d 100644
--- a/libs/WindowManager/Shell/res/values-pt-rPT/strings_tv.xml
+++ b/libs/WindowManager/Shell/res/values-pt-rPT/strings_tv.xml
@@ -24,4 +24,5 @@
<string name="pip_move" msgid="1544227837964635439">"Mover Ecrã no ecrã"</string>
<string name="pip_expand" msgid="7605396312689038178">"Expandir Ecrã no ecrã"</string>
<string name="pip_collapse" msgid="5732233773786896094">"Reduzir Ecrã no ecrã"</string>
+ <string name="pip_edu_text" msgid="3672999496647508701">" Prima duas vezes "<annotation icon="home_icon">" PÁGINA INICIAL "</annotation>" para controlos"</string>
</resources>
diff --git a/libs/WindowManager/Shell/res/values-pt/strings_tv.xml b/libs/WindowManager/Shell/res/values-pt/strings_tv.xml
index b669f16..cc4eb3c 100644
--- a/libs/WindowManager/Shell/res/values-pt/strings_tv.xml
+++ b/libs/WindowManager/Shell/res/values-pt/strings_tv.xml
@@ -24,4 +24,5 @@
<string name="pip_move" msgid="1544227837964635439">"Mover picture-in-picture"</string>
<string name="pip_expand" msgid="7605396312689038178">"Abrir picture-in-picture"</string>
<string name="pip_collapse" msgid="5732233773786896094">"Fechar picture-in-picture"</string>
+ <string name="pip_edu_text" msgid="3672999496647508701">" Pressione o botão "<annotation icon="home_icon">"home"</annotation>" duas vezes para acessar os controles"</string>
</resources>
diff --git a/libs/WindowManager/Shell/res/values-ro/strings_tv.xml b/libs/WindowManager/Shell/res/values-ro/strings_tv.xml
index 8ecf8c5..86a30f4 100644
--- a/libs/WindowManager/Shell/res/values-ro/strings_tv.xml
+++ b/libs/WindowManager/Shell/res/values-ro/strings_tv.xml
@@ -24,4 +24,5 @@
<string name="pip_move" msgid="1544227837964635439">"Mutați fereastra PIP"</string>
<string name="pip_expand" msgid="7605396312689038178">"Extindeți fereastra PIP"</string>
<string name="pip_collapse" msgid="5732233773786896094">"Restrângeți fereastra PIP"</string>
+ <string name="pip_edu_text" msgid="3672999496647508701">" Apăsați de două ori "<annotation icon="home_icon">"butonul ecran de pornire"</annotation>" pentru comenzi"</string>
</resources>
diff --git a/libs/WindowManager/Shell/res/values-ru/strings_tv.xml b/libs/WindowManager/Shell/res/values-ru/strings_tv.xml
index 19f7a00..08623e1 100644
--- a/libs/WindowManager/Shell/res/values-ru/strings_tv.xml
+++ b/libs/WindowManager/Shell/res/values-ru/strings_tv.xml
@@ -24,4 +24,5 @@
<string name="pip_move" msgid="1544227837964635439">"Переместить PIP"</string>
<string name="pip_expand" msgid="7605396312689038178">"Развернуть PIP"</string>
<string name="pip_collapse" msgid="5732233773786896094">"Свернуть PIP"</string>
+ <string name="pip_edu_text" msgid="3672999496647508701">" Элементы управления: дважды нажмите "<annotation icon="home_icon">" кнопку главного экрана "</annotation></string>
</resources>
diff --git a/libs/WindowManager/Shell/res/values-si/strings_tv.xml b/libs/WindowManager/Shell/res/values-si/strings_tv.xml
index 7444369..fbb0ebb 100644
--- a/libs/WindowManager/Shell/res/values-si/strings_tv.xml
+++ b/libs/WindowManager/Shell/res/values-si/strings_tv.xml
@@ -24,4 +24,5 @@
<string name="pip_move" msgid="1544227837964635439">"PIP ගෙන යන්න"</string>
<string name="pip_expand" msgid="7605396312689038178">"PIP දිග හරින්න"</string>
<string name="pip_collapse" msgid="5732233773786896094">"PIP හකුළන්න"</string>
+ <string name="pip_edu_text" msgid="3672999496647508701">" පාලන සඳහා "<annotation icon="home_icon">" මුල් පිටුව "</annotation>" දෙවරක් ඔබන්න"</string>
</resources>
diff --git a/libs/WindowManager/Shell/res/values-sk/strings_tv.xml b/libs/WindowManager/Shell/res/values-sk/strings_tv.xml
index 1a8edf1..81cb0ea 100644
--- a/libs/WindowManager/Shell/res/values-sk/strings_tv.xml
+++ b/libs/WindowManager/Shell/res/values-sk/strings_tv.xml
@@ -24,4 +24,5 @@
<string name="pip_move" msgid="1544227837964635439">"Presunúť obraz v obraze"</string>
<string name="pip_expand" msgid="7605396312689038178">"Rozbaliť obraz v obraze"</string>
<string name="pip_collapse" msgid="5732233773786896094">"Zbaliť obraz v obraze"</string>
+ <string name="pip_edu_text" msgid="3672999496647508701">" Ovládanie zobraz. dvoj. stlač. "<annotation icon="home_icon">" TLAČIDLA PLOCHY "</annotation></string>
</resources>
diff --git a/libs/WindowManager/Shell/res/values-sl/strings_tv.xml b/libs/WindowManager/Shell/res/values-sl/strings_tv.xml
index c4c04c2..060aaa0 100644
--- a/libs/WindowManager/Shell/res/values-sl/strings_tv.xml
+++ b/libs/WindowManager/Shell/res/values-sl/strings_tv.xml
@@ -24,4 +24,5 @@
<string name="pip_move" msgid="1544227837964635439">"Premakni sliko v sliki"</string>
<string name="pip_expand" msgid="7605396312689038178">"Razširi sliko v sliki"</string>
<string name="pip_collapse" msgid="5732233773786896094">"Strni sliko v sliki"</string>
+ <string name="pip_edu_text" msgid="3672999496647508701">" Za kontrolnike dvakrat pritisnite gumb za "<annotation icon="home_icon">" ZAČETNI ZASLON "</annotation></string>
</resources>
diff --git a/libs/WindowManager/Shell/res/values-sq/strings_tv.xml b/libs/WindowManager/Shell/res/values-sq/strings_tv.xml
index 2771b89..9bfdb6a 100644
--- a/libs/WindowManager/Shell/res/values-sq/strings_tv.xml
+++ b/libs/WindowManager/Shell/res/values-sq/strings_tv.xml
@@ -24,4 +24,5 @@
<string name="pip_move" msgid="1544227837964635439">"Zhvendos PIP"</string>
<string name="pip_expand" msgid="7605396312689038178">"Zgjero PIP"</string>
<string name="pip_collapse" msgid="5732233773786896094">"Palos PIP"</string>
+ <string name="pip_edu_text" msgid="3672999496647508701">" Trokit dy herë "<annotation icon="home_icon">" KREU "</annotation>" për kontrollet"</string>
</resources>
diff --git a/libs/WindowManager/Shell/res/values-sr/strings_tv.xml b/libs/WindowManager/Shell/res/values-sr/strings_tv.xml
index 3244030..6bc5c87 100644
--- a/libs/WindowManager/Shell/res/values-sr/strings_tv.xml
+++ b/libs/WindowManager/Shell/res/values-sr/strings_tv.xml
@@ -24,4 +24,5 @@
<string name="pip_move" msgid="1544227837964635439">"Премести слику у слици"</string>
<string name="pip_expand" msgid="7605396312689038178">"Прошири слику у слици"</string>
<string name="pip_collapse" msgid="5732233773786896094">"Скупи слику у слици"</string>
+ <string name="pip_edu_text" msgid="3672999496647508701">" Двапут притисните "<annotation icon="home_icon">" HOME "</annotation>" за контроле"</string>
</resources>
diff --git a/libs/WindowManager/Shell/res/values-sv/strings_tv.xml b/libs/WindowManager/Shell/res/values-sv/strings_tv.xml
index 842c805..b3465ab 100644
--- a/libs/WindowManager/Shell/res/values-sv/strings_tv.xml
+++ b/libs/WindowManager/Shell/res/values-sv/strings_tv.xml
@@ -24,4 +24,5 @@
<string name="pip_move" msgid="1544227837964635439">"Flytta BIB"</string>
<string name="pip_expand" msgid="7605396312689038178">"Utöka bild-i-bild"</string>
<string name="pip_collapse" msgid="5732233773786896094">"Komprimera bild-i-bild"</string>
+ <string name="pip_edu_text" msgid="3672999496647508701">" Tryck snabbt två gånger på "<annotation icon="home_icon">" HEM "</annotation>" för kontroller"</string>
</resources>
diff --git a/libs/WindowManager/Shell/res/values-sw/strings_tv.xml b/libs/WindowManager/Shell/res/values-sw/strings_tv.xml
index 8728fd9..baff49e 100644
--- a/libs/WindowManager/Shell/res/values-sw/strings_tv.xml
+++ b/libs/WindowManager/Shell/res/values-sw/strings_tv.xml
@@ -24,4 +24,5 @@
<string name="pip_move" msgid="1544227837964635439">"Kuhamisha PIP"</string>
<string name="pip_expand" msgid="7605396312689038178">"Panua PIP"</string>
<string name="pip_collapse" msgid="5732233773786896094">"Kunja PIP"</string>
+ <string name="pip_edu_text" msgid="3672999496647508701">" Bonyeza mara mbili kitufe cha "<annotation icon="home_icon">" UKURASA WA KWANZA "</annotation>" kupata vidhibiti"</string>
</resources>
diff --git a/libs/WindowManager/Shell/res/values-ta/strings_tv.xml b/libs/WindowManager/Shell/res/values-ta/strings_tv.xml
index e325b1a..4439e29 100644
--- a/libs/WindowManager/Shell/res/values-ta/strings_tv.xml
+++ b/libs/WindowManager/Shell/res/values-ta/strings_tv.xml
@@ -24,4 +24,5 @@
<string name="pip_move" msgid="1544227837964635439">"PIPபை நகர்த்து"</string>
<string name="pip_expand" msgid="7605396312689038178">"PIPபை விரிவாக்கு"</string>
<string name="pip_collapse" msgid="5732233773786896094">"PIPபைச் சுருக்கு"</string>
+ <string name="pip_edu_text" msgid="3672999496647508701">" கட்டுப்பாடுகள்: "<annotation icon="home_icon">" முகப்பு "</annotation>" பட்டனை இருமுறை அழுத்துக"</string>
</resources>
diff --git a/libs/WindowManager/Shell/res/values-te/strings_tv.xml b/libs/WindowManager/Shell/res/values-te/strings_tv.xml
index 1381e67..3557934 100644
--- a/libs/WindowManager/Shell/res/values-te/strings_tv.xml
+++ b/libs/WindowManager/Shell/res/values-te/strings_tv.xml
@@ -24,4 +24,5 @@
<string name="pip_move" msgid="1544227837964635439">"PIPను తరలించండి"</string>
<string name="pip_expand" msgid="7605396312689038178">"PIPని విస్తరించండి"</string>
<string name="pip_collapse" msgid="5732233773786896094">"PIPని కుదించండి"</string>
+ <string name="pip_edu_text" msgid="3672999496647508701">" కంట్రోల్స్ కోసం "<annotation icon="home_icon">" HOME "</annotation>" బటన్ రెండుసార్లు నొక్కండి"</string>
</resources>
diff --git a/libs/WindowManager/Shell/res/values-th/strings_tv.xml b/libs/WindowManager/Shell/res/values-th/strings_tv.xml
index 6f00018..0a07d15 100644
--- a/libs/WindowManager/Shell/res/values-th/strings_tv.xml
+++ b/libs/WindowManager/Shell/res/values-th/strings_tv.xml
@@ -24,4 +24,5 @@
<string name="pip_move" msgid="1544227837964635439">"ย้าย PIP"</string>
<string name="pip_expand" msgid="7605396312689038178">"ขยาย PIP"</string>
<string name="pip_collapse" msgid="5732233773786896094">"ยุบ PIP"</string>
+ <string name="pip_edu_text" msgid="3672999496647508701">" กดปุ่ม "<annotation icon="home_icon">" หน้าแรก "</annotation>" สองครั้งเพื่อเปิดการควบคุม"</string>
</resources>
diff --git a/libs/WindowManager/Shell/res/values-tl/strings_tv.xml b/libs/WindowManager/Shell/res/values-tl/strings_tv.xml
index 868b278..9a11a38 100644
--- a/libs/WindowManager/Shell/res/values-tl/strings_tv.xml
+++ b/libs/WindowManager/Shell/res/values-tl/strings_tv.xml
@@ -24,4 +24,5 @@
<string name="pip_move" msgid="1544227837964635439">"Ilipat ang PIP"</string>
<string name="pip_expand" msgid="7605396312689038178">"I-expand ang PIP"</string>
<string name="pip_collapse" msgid="5732233773786896094">"I-collapse ang PIP"</string>
+ <string name="pip_edu_text" msgid="3672999496647508701">" I-double press ang "<annotation icon="home_icon">" HOME "</annotation>" para sa mga kontrol"</string>
</resources>
diff --git a/libs/WindowManager/Shell/res/values-tr/strings_tv.xml b/libs/WindowManager/Shell/res/values-tr/strings_tv.xml
index 9ffad78..bf4bc6f 100644
--- a/libs/WindowManager/Shell/res/values-tr/strings_tv.xml
+++ b/libs/WindowManager/Shell/res/values-tr/strings_tv.xml
@@ -24,4 +24,5 @@
<string name="pip_move" msgid="1544227837964635439">"PIP\'yi taşı"</string>
<string name="pip_expand" msgid="7605396312689038178">"PIP penceresini genişlet"</string>
<string name="pip_collapse" msgid="5732233773786896094">"PIP penceresini daralt"</string>
+ <string name="pip_edu_text" msgid="3672999496647508701">" Kontroller için "<annotation icon="home_icon">" ANA SAYFA "</annotation>"\'ya iki kez basın"</string>
</resources>
diff --git a/libs/WindowManager/Shell/res/values-uk/strings_tv.xml b/libs/WindowManager/Shell/res/values-uk/strings_tv.xml
index 24c1698..7e9f54e 100644
--- a/libs/WindowManager/Shell/res/values-uk/strings_tv.xml
+++ b/libs/WindowManager/Shell/res/values-uk/strings_tv.xml
@@ -24,4 +24,5 @@
<string name="pip_move" msgid="1544227837964635439">"Перемістити картинку в картинці"</string>
<string name="pip_expand" msgid="7605396312689038178">"Розгорнути картинку в картинці"</string>
<string name="pip_collapse" msgid="5732233773786896094">"Згорнути картинку в картинці"</string>
+ <string name="pip_edu_text" msgid="3672999496647508701">" Відкрити елементи керування: двічі натисніть "<annotation icon="home_icon">"HOME"</annotation></string>
</resources>
diff --git a/libs/WindowManager/Shell/res/values-ur/strings_tv.xml b/libs/WindowManager/Shell/res/values-ur/strings_tv.xml
index c05729a..c2ef69f 100644
--- a/libs/WindowManager/Shell/res/values-ur/strings_tv.xml
+++ b/libs/WindowManager/Shell/res/values-ur/strings_tv.xml
@@ -24,4 +24,5 @@
<string name="pip_move" msgid="1544227837964635439">"PIP کو منتقل کریں"</string>
<string name="pip_expand" msgid="7605396312689038178">"PIP کو پھیلائیں"</string>
<string name="pip_collapse" msgid="5732233773786896094">"PIP کو سکیڑیں"</string>
+ <string name="pip_edu_text" msgid="3672999496647508701">" کنٹرولز کے لیے "<annotation icon="home_icon">"ہوم "</annotation>" بٹن کو دو بار دبائیں"</string>
</resources>
diff --git a/libs/WindowManager/Shell/res/values-uz/strings_tv.xml b/libs/WindowManager/Shell/res/values-uz/strings_tv.xml
index 43ab5ac..9ab95c8 100644
--- a/libs/WindowManager/Shell/res/values-uz/strings_tv.xml
+++ b/libs/WindowManager/Shell/res/values-uz/strings_tv.xml
@@ -24,4 +24,5 @@
<string name="pip_move" msgid="1544227837964635439">"PIPni siljitish"</string>
<string name="pip_expand" msgid="7605396312689038178">"PIP funksiyasini yoyish"</string>
<string name="pip_collapse" msgid="5732233773786896094">"PIP funksiyasini yopish"</string>
+ <string name="pip_edu_text" msgid="3672999496647508701">" Boshqaruv uchun "<annotation icon="home_icon">"ASOSIY"</annotation>" tugmani ikki marta bosing"</string>
</resources>
diff --git a/libs/WindowManager/Shell/res/values-vi/strings_tv.xml b/libs/WindowManager/Shell/res/values-vi/strings_tv.xml
index 368280c..146376d 100644
--- a/libs/WindowManager/Shell/res/values-vi/strings_tv.xml
+++ b/libs/WindowManager/Shell/res/values-vi/strings_tv.xml
@@ -24,4 +24,5 @@
<string name="pip_move" msgid="1544227837964635439">"Di chuyển PIP (Ảnh trong ảnh)"</string>
<string name="pip_expand" msgid="7605396312689038178">"Mở rộng PIP (Ảnh trong ảnh)"</string>
<string name="pip_collapse" msgid="5732233773786896094">"Thu gọn PIP (Ảnh trong ảnh)"</string>
+ <string name="pip_edu_text" msgid="3672999496647508701">" Nhấn đúp vào nút "<annotation icon="home_icon">" MÀN HÌNH CHÍNH "</annotation>" để mở trình đơn điều khiển"</string>
</resources>
diff --git a/libs/WindowManager/Shell/res/values-zh-rCN/strings_tv.xml b/libs/WindowManager/Shell/res/values-zh-rCN/strings_tv.xml
index e5d879a..55407d2 100644
--- a/libs/WindowManager/Shell/res/values-zh-rCN/strings_tv.xml
+++ b/libs/WindowManager/Shell/res/values-zh-rCN/strings_tv.xml
@@ -24,4 +24,5 @@
<string name="pip_move" msgid="1544227837964635439">"移动画中画窗口"</string>
<string name="pip_expand" msgid="7605396312689038178">"展开 PIP"</string>
<string name="pip_collapse" msgid="5732233773786896094">"收起 PIP"</string>
+ <string name="pip_edu_text" msgid="3672999496647508701">" 按两次"<annotation icon="home_icon">"主屏幕"</annotation>"按钮可查看相关控件"</string>
</resources>
diff --git a/libs/WindowManager/Shell/res/values-zh-rHK/strings_tv.xml b/libs/WindowManager/Shell/res/values-zh-rHK/strings_tv.xml
index 8ee5f11..15e278d 100644
--- a/libs/WindowManager/Shell/res/values-zh-rHK/strings_tv.xml
+++ b/libs/WindowManager/Shell/res/values-zh-rHK/strings_tv.xml
@@ -24,4 +24,5 @@
<string name="pip_move" msgid="1544227837964635439">"移動畫中畫"</string>
<string name="pip_expand" msgid="7605396312689038178">"展開畫中畫"</string>
<string name="pip_collapse" msgid="5732233773786896094">"收合畫中畫"</string>
+ <string name="pip_edu_text" msgid="3672999496647508701">" 按兩下"<annotation icon="home_icon">" 主畫面按鈕"</annotation>"即可顯示控制項"</string>
</resources>
diff --git a/libs/WindowManager/Shell/res/values-zh-rTW/strings_tv.xml b/libs/WindowManager/Shell/res/values-zh-rTW/strings_tv.xml
index b23ecde..0b17b31 100644
--- a/libs/WindowManager/Shell/res/values-zh-rTW/strings_tv.xml
+++ b/libs/WindowManager/Shell/res/values-zh-rTW/strings_tv.xml
@@ -24,4 +24,5 @@
<string name="pip_move" msgid="1544227837964635439">"移動子母畫面"</string>
<string name="pip_expand" msgid="7605396312689038178">"展開子母畫面"</string>
<string name="pip_collapse" msgid="5732233773786896094">"收合子母畫面"</string>
+ <string name="pip_edu_text" msgid="3672999496647508701">" 按兩下"<annotation icon="home_icon">"主畫面按鈕"</annotation>"即可顯示控制選項"</string>
</resources>
diff --git a/libs/WindowManager/Shell/res/values-zu/strings_tv.xml b/libs/WindowManager/Shell/res/values-zu/strings_tv.xml
index b14ee99..dad8c81 100644
--- a/libs/WindowManager/Shell/res/values-zu/strings_tv.xml
+++ b/libs/WindowManager/Shell/res/values-zu/strings_tv.xml
@@ -24,4 +24,5 @@
<string name="pip_move" msgid="1544227837964635439">"Hambisa i-PIP"</string>
<string name="pip_expand" msgid="7605396312689038178">"Nweba i-PIP"</string>
<string name="pip_collapse" msgid="5732233773786896094">"Goqa i-PIP"</string>
+ <string name="pip_edu_text" msgid="3672999496647508701">" Chofoza kabili "<annotation icon="home_icon">" IKHAYA"</annotation>" mayelana nezilawuli"</string>
</resources>
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/ShellTaskOrganizer.java b/libs/WindowManager/Shell/src/com/android/wm/shell/ShellTaskOrganizer.java
index 8442994..31f0ef0 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/ShellTaskOrganizer.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/ShellTaskOrganizer.java
@@ -165,8 +165,12 @@
private StartingWindowController mStartingWindow;
/**
- * In charge of showing compat UI. Can be {@code null} if device doesn't support size
- * compat.
+ * In charge of showing compat UI. Can be {@code null} if the device doesn't support size
+ * compat or if this isn't the main {@link ShellTaskOrganizer}.
+ *
+ * <p>NOTE: only the main {@link ShellTaskOrganizer} should have a {@link CompatUIController},
+ * and register itself as a {@link CompatUIController.CompatUICallback}. Subclasses should be
+ * initialized with a {@code null} {@link CompatUIController}.
*/
@Nullable
private final CompatUIController mCompatUI;
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/back/BackAnimationController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/back/BackAnimationController.java
index 8d5fdfb..08cb252 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/back/BackAnimationController.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/back/BackAnimationController.java
@@ -52,14 +52,17 @@
*/
public class BackAnimationController implements RemoteCallable<BackAnimationController> {
- private static final String BACK_PREDICTABILITY_PROP = "persist.debug.back_predictability";
- public static final boolean IS_ENABLED = SystemProperties
- .getInt(BACK_PREDICTABILITY_PROP, 0) > 0;
private static final String BACK_PREDICTABILITY_PROGRESS_THRESHOLD_PROP =
"persist.debug.back_predictability_progress_threshold";
+ // By default, enable new back dispatching without any animations.
+ private static final int BACK_PREDICTABILITY_PROP =
+ SystemProperties.getInt("persist.debug.back_predictability", 1);
+ public static final boolean IS_ENABLED = BACK_PREDICTABILITY_PROP > 0;
private static final int PROGRESS_THRESHOLD = SystemProperties
.getInt(BACK_PREDICTABILITY_PROGRESS_THRESHOLD_PROP, -1);
private static final String TAG = "BackAnimationController";
+ @VisibleForTesting
+ boolean mEnableAnimations = (BACK_PREDICTABILITY_PROP & (1 << 1)) != 0;
/**
* Location of the initial touch event of the back gesture.
@@ -255,7 +258,7 @@
backNavigationInfo.getTaskWindowConfiguration());
}
mTransaction.apply();
- } else if (backType == BackNavigationInfo.TYPE_RETURN_TO_HOME) {
+ } else if (shouldDispatchToLauncher(backType)) {
targetCallback = mBackToLauncherCallback;
} else if (backType == BackNavigationInfo.TYPE_CALLBACK) {
targetCallback = mBackNavigationInfo.getOnBackInvokedCallback();
@@ -309,7 +312,7 @@
BackEvent backEvent = new BackEvent(0, 0, progress, swipeEdge, animationTarget);
IOnBackInvokedCallback targetCallback = null;
- if (backType == BackNavigationInfo.TYPE_RETURN_TO_HOME) {
+ if (shouldDispatchToLauncher(backType)) {
targetCallback = mBackToLauncherCallback;
} else if (backType == BackNavigationInfo.TYPE_CROSS_TASK
|| backType == BackNavigationInfo.TYPE_CROSS_ACTIVITY) {
@@ -330,8 +333,7 @@
return;
}
int backType = mBackNavigationInfo.getType();
- boolean shouldDispatchToLauncher = backType == BackNavigationInfo.TYPE_RETURN_TO_HOME
- && mBackToLauncherCallback != null;
+ boolean shouldDispatchToLauncher = shouldDispatchToLauncher(backType);
IOnBackInvokedCallback targetCallback = shouldDispatchToLauncher
? mBackToLauncherCallback
: mBackNavigationInfo.getOnBackInvokedCallback();
@@ -356,6 +358,17 @@
}
}
+ private boolean shouldDispatchToLauncher(int backType) {
+ return backType == BackNavigationInfo.TYPE_RETURN_TO_HOME
+ && mBackToLauncherCallback != null
+ && mEnableAnimations;
+ }
+
+ @VisibleForTesting
+ void setEnableAnimations(boolean shouldEnable) {
+ mEnableAnimations = shouldEnable;
+ }
+
private static void dispatchOnBackStarted(IOnBackInvokedCallback callback) {
if (callback == null) {
return;
@@ -468,7 +481,7 @@
return;
}
RemoteAnimationTarget animationTarget = backNavigationInfo.getDepartingAnimationTarget();
- if (animationTarget != null && mTriggerBack) {
+ if (animationTarget != null) {
if (animationTarget.leash != null && animationTarget.leash.isValid()) {
mTransaction.remove(animationTarget.leash);
}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleStackView.java b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleStackView.java
index 58f79f3..13d12b3 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleStackView.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleStackView.java
@@ -1049,10 +1049,17 @@
private final Runnable mAnimateTemporarilyInvisibleImmediate = () -> {
if (mTemporarilyInvisible && mFlyout.getVisibility() != View.VISIBLE) {
+ // To calculate a distance, bubble stack needs to be moved to become hidden,
+ // we need to take into account that the bubble stack is positioned on the edge
+ // of the available screen rect, which can be offset by system bars and cutouts.
if (mStackAnimationController.isStackOnLeftSide()) {
- animate().translationX(-mBubbleSize).start();
+ int availableRectOffsetX =
+ mPositioner.getAvailableRect().left - mPositioner.getScreenRect().left;
+ animate().translationX(-(mBubbleSize + availableRectOffsetX)).start();
} else {
- animate().translationX(mBubbleSize).start();
+ int availableRectOffsetX =
+ mPositioner.getAvailableRect().right - mPositioner.getScreenRect().right;
+ animate().translationX(mBubbleSize - availableRectOffsetX).start();
}
} else {
animate().translationX(0).start();
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/common/SystemWindows.java b/libs/WindowManager/Shell/src/com/android/wm/shell/common/SystemWindows.java
index 51067a4..4583389 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/common/SystemWindows.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/common/SystemWindows.java
@@ -344,7 +344,7 @@
@Override
public void resized(ClientWindowFrames frames, boolean reportDraw,
MergedConfiguration newMergedConfiguration, boolean forceLayout,
- boolean alwaysConsumeSystemBars, int displayId) {}
+ boolean alwaysConsumeSystemBars, int displayId, int syncSeqId) {}
@Override
public void insetsChanged(InsetsState insetsState, boolean willMove, boolean willResize) {}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/SplitLayout.java b/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/SplitLayout.java
index b52c8d1..daba774 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/SplitLayout.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/SplitLayout.java
@@ -98,6 +98,7 @@
private WindowContainerToken mWinToken2;
private int mDividePosition;
private boolean mInitialized = false;
+ private boolean mFreezeDividerWindow = false;
private int mOrientation;
private int mRotation;
@@ -225,11 +226,6 @@
mDividerSnapAlgorithm = getSnapAlgorithm(mContext, mRootBounds, null);
initDividerPosition(mTempRect);
- if (mInitialized) {
- release();
- init();
- }
-
return true;
}
@@ -298,20 +294,37 @@
}
/** Releases the surface holding the current {@link DividerView}. */
- public void release() {
+ public void release(SurfaceControl.Transaction t) {
if (!mInitialized) return;
mInitialized = false;
- mSplitWindowManager.release();
+ mSplitWindowManager.release(t);
mDisplayImeController.removePositionProcessor(mImePositionProcessor);
mImePositionProcessor.reset();
}
+ public void release() {
+ release(null /* t */);
+ }
+
+ /** Releases and re-inflates {@link DividerView} on the root surface. */
+ public void update(SurfaceControl.Transaction t) {
+ if (!mInitialized) return;
+ mSplitWindowManager.release(t);
+ mImePositionProcessor.reset();
+ mSplitWindowManager.init(this, mInsetsState);
+ }
+
@Override
public void insetsChanged(InsetsState insetsState) {
mInsetsState.set(insetsState);
if (!mInitialized) {
return;
}
+ if (mFreezeDividerWindow) {
+ // DO NOT change its layout before transition actually run because it might cause
+ // flicker.
+ return;
+ }
mSplitWindowManager.onInsetsChanged(insetsState);
}
@@ -323,6 +336,10 @@
}
}
+ public void setFreezeDividerWindow(boolean freezeDividerWindow) {
+ mFreezeDividerWindow = freezeDividerWindow;
+ }
+
/**
* Updates bounds with the passing position. Usually used to update recording bounds while
* performing animation or dragging divider bar to resize the splits.
@@ -515,7 +532,9 @@
}
private int getSmallestWidthDp(Rect bounds) {
- final int minWidth = Math.min(bounds.width(), bounds.height());
+ mTempRect.set(bounds);
+ mTempRect.inset(getDisplayInsets(mContext));
+ final int minWidth = Math.min(mTempRect.width(), mTempRect.height());
final float density = mContext.getResources().getDisplayMetrics().density;
return (int) (minWidth / density);
}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/SplitWindowManager.java b/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/SplitWindowManager.java
index 4903f9d..833d9d5 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/SplitWindowManager.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/SplitWindowManager.java
@@ -58,6 +58,9 @@
private SurfaceControl mLeash;
private DividerView mDividerView;
+ // Used to "pass" a transaction to WWM.remove so that view removal can be synchronized.
+ private SurfaceControl.Transaction mSyncTransaction = null;
+
public interface ParentContainerCallbacks {
void attachToParentSurface(SurfaceControl.Builder b);
void onLeashReady(SurfaceControl leash);
@@ -130,22 +133,38 @@
* Releases the surface control of the current {@link DividerView} and tear down the view
* hierarchy.
*/
- void release() {
+ void release(@Nullable SurfaceControl.Transaction t) {
if (mDividerView != null) {
mDividerView = null;
}
if (mViewHost != null){
+ mSyncTransaction = t;
mViewHost.release();
+ mSyncTransaction = null;
mViewHost = null;
}
if (mLeash != null) {
- new SurfaceControl.Transaction().remove(mLeash).apply();
+ if (t == null) {
+ new SurfaceControl.Transaction().remove(mLeash).apply();
+ } else {
+ t.remove(mLeash);
+ }
mLeash = null;
}
}
+ @Override
+ protected void removeSurface(SurfaceControl sc) {
+ // This gets called via SurfaceControlViewHost.release()
+ if (mSyncTransaction != null) {
+ mSyncTransaction.remove(sc);
+ } else {
+ super.removeSurface(sc);
+ }
+ }
+
void setInteractive(boolean interactive) {
if (mDividerView == null) return;
mDividerView.setInteractive(interactive);
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/compatui/CompatUIController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/compatui/CompatUIController.java
index b2bbafe..99b32a6 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/compatui/CompatUIController.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/compatui/CompatUIController.java
@@ -42,6 +42,7 @@
import com.android.wm.shell.common.annotations.ExternalThread;
import com.android.wm.shell.compatui.CompatUIWindowManager.CompatUIHintsState;
import com.android.wm.shell.compatui.letterboxedu.LetterboxEduWindowManager;
+import com.android.wm.shell.transition.Transitions;
import java.lang.ref.WeakReference;
import java.util.ArrayList;
@@ -50,6 +51,8 @@
import java.util.function.Consumer;
import java.util.function.Predicate;
+import dagger.Lazy;
+
/**
* Controller to show/update compat UI components on Tasks based on whether the foreground
* activities are in compatibility mode.
@@ -102,6 +105,7 @@
private final DisplayImeController mImeController;
private final SyncTransactionQueue mSyncQueue;
private final ShellExecutor mMainExecutor;
+ private final Lazy<Transitions> mTransitionsLazy;
private final CompatUIImpl mImpl = new CompatUIImpl();
private CompatUICallback mCallback;
@@ -118,13 +122,15 @@
DisplayInsetsController displayInsetsController,
DisplayImeController imeController,
SyncTransactionQueue syncQueue,
- ShellExecutor mainExecutor) {
+ ShellExecutor mainExecutor,
+ Lazy<Transitions> transitionsLazy) {
mContext = context;
mDisplayController = displayController;
mDisplayInsetsController = displayInsetsController;
mImeController = imeController;
mSyncQueue = syncQueue;
mMainExecutor = mainExecutor;
+ mTransitionsLazy = transitionsLazy;
mDisplayController.addDisplayWindowListener(this);
mImeController.addPositionProcessor(this);
mCompatUIHintsState = new CompatUIHintsState();
@@ -302,6 +308,7 @@
ShellTaskOrganizer.TaskListener taskListener) {
return new LetterboxEduWindowManager(context, taskInfo,
mSyncQueue, taskListener, mDisplayController.getDisplayLayout(taskInfo.displayId),
+ mTransitionsLazy.get(),
this::onLetterboxEduDismissed);
}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/compatui/letterboxedu/LetterboxEduAnimationController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/compatui/letterboxedu/LetterboxEduAnimationController.java
index 03986ee..3061eab 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/compatui/letterboxedu/LetterboxEduAnimationController.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/compatui/letterboxedu/LetterboxEduAnimationController.java
@@ -18,6 +18,7 @@
import static com.android.internal.R.styleable.WindowAnimation_windowEnterAnimation;
import static com.android.internal.R.styleable.WindowAnimation_windowExitAnimation;
+import static com.android.wm.shell.transition.Transitions.ENABLE_SHELL_TRANSITIONS;
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
@@ -42,7 +43,9 @@
class LetterboxEduAnimationController {
private static final String TAG = "LetterboxEduAnimation";
- private static final int ENTER_ANIM_START_DELAY_MILLIS = 500;
+ // If shell transitions are enabled, startEnterAnimation will be called after all transitions
+ // have finished, and therefore the start delay should be shorter.
+ private static final int ENTER_ANIM_START_DELAY_MILLIS = ENABLE_SHELL_TRANSITIONS ? 300 : 500;
private final TransitionAnimation mTransitionAnimation;
private final String mPackageName;
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/compatui/letterboxedu/LetterboxEduDialogLayout.java b/libs/WindowManager/Shell/src/com/android/wm/shell/compatui/letterboxedu/LetterboxEduDialogLayout.java
index 8aa4d0e..2e0b09e 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/compatui/letterboxedu/LetterboxEduDialogLayout.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/compatui/letterboxedu/LetterboxEduDialogLayout.java
@@ -38,6 +38,7 @@
// The alpha of a background is a number between 0 (fully transparent) to 255 (fully opaque).
// 204 is simply 255 * 0.8.
static final int BACKGROUND_DIM_ALPHA = 204;
+
private View mDialogContainer;
private TextView mDialogTitle;
private Drawable mBackgroundDim;
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/compatui/letterboxedu/LetterboxEduWindowManager.java b/libs/WindowManager/Shell/src/com/android/wm/shell/compatui/letterboxedu/LetterboxEduWindowManager.java
index dda72ff..cc3a3b2 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/compatui/letterboxedu/LetterboxEduWindowManager.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/compatui/letterboxedu/LetterboxEduWindowManager.java
@@ -36,6 +36,7 @@
import com.android.wm.shell.common.DisplayLayout;
import com.android.wm.shell.common.SyncTransactionQueue;
import com.android.wm.shell.compatui.CompatUIWindowManagerAbstract;
+import com.android.wm.shell.transition.Transitions;
/**
* Window manager for the Letterbox Education.
@@ -63,6 +64,8 @@
private final LetterboxEduAnimationController mAnimationController;
+ private final Transitions mTransitions;
+
// Remember the last reported state in case visibility changes due to keyguard or IME updates.
private boolean mEligibleForLetterboxEducation;
@@ -80,17 +83,19 @@
public LetterboxEduWindowManager(Context context, TaskInfo taskInfo,
SyncTransactionQueue syncQueue, ShellTaskOrganizer.TaskListener taskListener,
- DisplayLayout displayLayout, Runnable onDismissCallback) {
- this(context, taskInfo, syncQueue, taskListener, displayLayout, onDismissCallback,
- new LetterboxEduAnimationController(context));
+ DisplayLayout displayLayout, Transitions transitions,
+ Runnable onDismissCallback) {
+ this(context, taskInfo, syncQueue, taskListener, displayLayout, transitions,
+ onDismissCallback, new LetterboxEduAnimationController(context));
}
@VisibleForTesting
LetterboxEduWindowManager(Context context, TaskInfo taskInfo,
SyncTransactionQueue syncQueue, ShellTaskOrganizer.TaskListener taskListener,
- DisplayLayout displayLayout, Runnable onDismissCallback,
+ DisplayLayout displayLayout, Transitions transitions, Runnable onDismissCallback,
LetterboxEduAnimationController animationController) {
super(context, taskInfo, syncQueue, taskListener, displayLayout);
+ mTransitions = transitions;
mOnDismissCallback = onDismissCallback;
mAnimationController = animationController;
mEligibleForLetterboxEducation = taskInfo.topActivityEligibleForLetterboxEducation;
@@ -132,8 +137,8 @@
mLayout = inflateLayout();
updateDialogMargins();
- mAnimationController.startEnterAnimation(mLayout, /* endCallback= */
- this::onDialogEnterAnimationEnded);
+ // startEnterAnimation will be called immediately if shell-transitions are disabled.
+ mTransitions.runOnIdle(this::startEnterAnimation);
return mLayout;
}
@@ -158,8 +163,18 @@
R.layout.letterbox_education_dialog_layout, null);
}
+ private void startEnterAnimation() {
+ if (mLayout == null) {
+ // Dialog has already been released.
+ return;
+ }
+ mAnimationController.startEnterAnimation(mLayout, /* endCallback= */
+ this::onDialogEnterAnimationEnded);
+ }
+
private void onDialogEnterAnimationEnded() {
if (mLayout == null) {
+ // Dialog has already been released.
return;
}
mLayout.setDismissOnClickListener(this::onDismiss);
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/WMShellBaseModule.java b/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/WMShellBaseModule.java
index bf0337d..026eeb0 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/WMShellBaseModule.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/WMShellBaseModule.java
@@ -96,6 +96,7 @@
import java.util.Optional;
import dagger.BindsOptionalOf;
+import dagger.Lazy;
import dagger.Module;
import dagger.Provides;
@@ -189,15 +190,13 @@
@ShellMainThread ShellExecutor mainExecutor,
@ShellMainThread Handler mainHandler,
Context context,
- CompatUIController compatUI,
SyncTransactionQueue syncTransactionQueue,
DisplayController displayController,
DisplayInsetsController displayInsetsController,
Optional<RecentTasksController> recentTasksOptional
) {
- return new KidsModeTaskOrganizer(mainExecutor, mainHandler, context, compatUI,
- syncTransactionQueue, displayController, displayInsetsController,
- recentTasksOptional);
+ return new KidsModeTaskOrganizer(mainExecutor, mainHandler, context, syncTransactionQueue,
+ displayController, displayInsetsController, recentTasksOptional);
}
@WMSingleton
@@ -210,9 +209,9 @@
static CompatUIController provideCompatUIController(Context context,
DisplayController displayController, DisplayInsetsController displayInsetsController,
DisplayImeController imeController, SyncTransactionQueue syncQueue,
- @ShellMainThread ShellExecutor mainExecutor) {
+ @ShellMainThread ShellExecutor mainExecutor, Lazy<Transitions> transitionsLazy) {
return new CompatUIController(context, displayController, displayInsetsController,
- imeController, syncQueue, mainExecutor);
+ imeController, syncQueue, mainExecutor, transitionsLazy);
}
@WMSingleton
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/kidsmode/KidsModeTaskOrganizer.java b/libs/WindowManager/Shell/src/com/android/wm/shell/kidsmode/KidsModeTaskOrganizer.java
index 429eb99..003c559 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/kidsmode/KidsModeTaskOrganizer.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/kidsmode/KidsModeTaskOrganizer.java
@@ -38,7 +38,6 @@
import android.window.WindowContainerTransaction;
import androidx.annotation.NonNull;
-import androidx.annotation.Nullable;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.policy.ForceShowNavigationBarSettingsObserver;
@@ -48,7 +47,6 @@
import com.android.wm.shell.common.DisplayLayout;
import com.android.wm.shell.common.ShellExecutor;
import com.android.wm.shell.common.SyncTransactionQueue;
-import com.android.wm.shell.compatui.CompatUIController;
import com.android.wm.shell.recents.RecentTasksController;
import com.android.wm.shell.startingsurface.StartingWindowController;
@@ -136,13 +134,12 @@
ShellExecutor mainExecutor,
Handler mainHandler,
Context context,
- @Nullable CompatUIController compatUI,
SyncTransactionQueue syncTransactionQueue,
DisplayController displayController,
DisplayInsetsController displayInsetsController,
Optional<RecentTasksController> recentTasks,
ForceShowNavigationBarSettingsObserver forceShowNavigationBarSettingsObserver) {
- super(taskOrganizerController, mainExecutor, context, compatUI, recentTasks);
+ super(taskOrganizerController, mainExecutor, context, /* compatUI= */ null, recentTasks);
mContext = context;
mMainHandler = mainHandler;
mSyncQueue = syncTransactionQueue;
@@ -155,12 +152,11 @@
ShellExecutor mainExecutor,
Handler mainHandler,
Context context,
- @Nullable CompatUIController compatUI,
SyncTransactionQueue syncTransactionQueue,
DisplayController displayController,
DisplayInsetsController displayInsetsController,
Optional<RecentTasksController> recentTasks) {
- super(mainExecutor, context, compatUI, recentTasks);
+ super(mainExecutor, context, /* compatUI= */ null, recentTasks);
mContext = context;
mMainHandler = mainHandler;
mSyncQueue = syncTransactionQueue;
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipBoundsAlgorithm.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipBoundsAlgorithm.java
index c2d5823..7397e52 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipBoundsAlgorithm.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipBoundsAlgorithm.java
@@ -194,7 +194,7 @@
public float getAspectRatioOrDefault(
@android.annotation.Nullable PictureInPictureParams params) {
return params != null && params.hasSetAspectRatio()
- ? params.getAspectRatio()
+ ? params.getAspectRatioFloat()
: getDefaultAspectRatio();
}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTaskOrganizer.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTaskOrganizer.java
index c1e7825..5d6b041 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTaskOrganizer.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTaskOrganizer.java
@@ -1071,13 +1071,13 @@
*/
private boolean applyPictureInPictureParams(@NonNull PictureInPictureParams params) {
final Rational currentAspectRatio =
- mPictureInPictureParams != null ? mPictureInPictureParams.getAspectRatioRational()
+ mPictureInPictureParams != null ? mPictureInPictureParams.getAspectRatio()
: null;
final boolean aspectRatioChanged = !Objects.equals(currentAspectRatio,
- params.getAspectRatioRational());
+ params.getAspectRatio());
mPictureInPictureParams = params;
if (aspectRatioChanged) {
- mPipBoundsState.setAspectRatio(params.getAspectRatio());
+ mPipBoundsState.setAspectRatio(params.getAspectRatioFloat());
}
return aspectRatioChanged;
}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTransition.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTransition.java
index be713a5..e5a755c 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTransition.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTransition.java
@@ -166,8 +166,7 @@
mExitTransition = null;
mHasFadeOut = false;
if (mFinishCallback != null) {
- mFinishCallback.onTransitionFinished(null, null);
- mFinishCallback = null;
+ callFinishCallback(null /* wct */);
mFinishTransaction = null;
throw new RuntimeException("Previous callback not called, aborting exit PIP.");
}
@@ -232,6 +231,11 @@
return false;
}
+ /** Helper to identify whether this handler is currently the one playing an animation */
+ private boolean isAnimatingLocally() {
+ return mFinishTransaction != null;
+ }
+
@Nullable
@Override
public WindowContainerTransaction handleRequest(@NonNull IBinder transition,
@@ -282,9 +286,11 @@
if (enteringPip) {
mPipTransitionState.setTransitionState(ENTERED_PIP);
}
- // If there is an expected exit transition, then the exit will be "merged" into this
- // transition so don't fire the finish-callback in that case.
- if (mExitTransition == null && mFinishCallback != null) {
+ // If we have an exit transition, but aren't playing a transition locally, it
+ // means we're expecting the exit transition will be "merged" into another transition
+ // (likely a remote like launcher), so don't fire the finish-callback here -- wait until
+ // the exit transition is merged.
+ if ((mExitTransition == null || isAnimatingLocally()) && mFinishCallback != null) {
WindowContainerTransaction wct = new WindowContainerTransaction();
prepareFinishResizeTransaction(taskInfo, destinationBounds,
direction, wct);
@@ -305,12 +311,19 @@
mSurfaceTransactionHelper.crop(mFinishTransaction, leash, finishBounds);
}
mFinishTransaction = null;
- mFinishCallback.onTransitionFinished(wct, null /* callback */);
- mFinishCallback = null;
+ callFinishCallback(wct);
}
finishResizeForMenu(destinationBounds);
}
+ private void callFinishCallback(WindowContainerTransaction wct) {
+ // Need to unset mFinishCallback first because onTransitionFinished can re-enter this
+ // handler if there is a pending PiP animation.
+ final Transitions.TransitionFinishCallback finishCallback = mFinishCallback;
+ mFinishCallback = null;
+ finishCallback.onTransitionFinished(wct, null /* callback */);
+ }
+
@Override
public void forceFinishTransition() {
if (mFinishCallback == null) return;
@@ -572,8 +585,7 @@
mHasFadeOut = false;
if (mFinishCallback != null) {
- mFinishCallback.onTransitionFinished(null /* wct */, null /* callback */);
- mFinishCallback = null;
+ callFinishCallback(null /* wct */);
mFinishTransaction = null;
throw new RuntimeException("Previous callback not called, aborting entering PIP.");
}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipDismissTargetHandler.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipDismissTargetHandler.java
index 3115f8a..11633a9 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipDismissTargetHandler.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipDismissTargetHandler.java
@@ -253,11 +253,11 @@
private WindowManager.LayoutParams getDismissTargetLayoutParams() {
final Point windowSize = new Point();
mWindowManager.getDefaultDisplay().getRealSize(windowSize);
-
+ int height = Math.min(windowSize.y, mDismissAreaHeight);
final WindowManager.LayoutParams lp = new WindowManager.LayoutParams(
WindowManager.LayoutParams.MATCH_PARENT,
- mDismissAreaHeight,
- 0, windowSize.y - mDismissAreaHeight,
+ height,
+ 0, windowSize.y - height,
WindowManager.LayoutParams.TYPE_NAVIGATION_BAR_PANEL,
WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN
| WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/tv/TvPipBoundsState.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/tv/TvPipBoundsState.java
index d880f82..9865548 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/tv/TvPipBoundsState.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/tv/TvPipBoundsState.java
@@ -75,7 +75,7 @@
public void setBoundsStateForEntry(ComponentName componentName, ActivityInfo activityInfo,
PictureInPictureParams params, PipBoundsAlgorithm pipBoundsAlgorithm) {
super.setBoundsStateForEntry(componentName, activityInfo, params, pipBoundsAlgorithm);
- setDesiredTvExpandedAspectRatio(params.getExpandedAspectRatio(), true);
+ setDesiredTvExpandedAspectRatio(params.getExpandedAspectRatioFloat(), true);
}
/** Resets the TV PiP state for a new activity. */
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreenController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreenController.java
index e88eef9..2da5bec 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreenController.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreenController.java
@@ -18,12 +18,14 @@
import static android.app.ActivityManager.START_SUCCESS;
import static android.app.ActivityManager.START_TASK_TO_FRONT;
+import static android.content.Intent.FLAG_ACTIVITY_NO_USER_ACTION;
import static android.view.Display.DEFAULT_DISPLAY;
import static android.view.RemoteAnimationTarget.MODE_OPENING;
import static com.android.wm.shell.common.ExecutorUtils.executeRemoteCallWithTaskPermission;
import static com.android.wm.shell.common.split.SplitScreenConstants.SPLIT_POSITION_BOTTOM_OR_RIGHT;
import static com.android.wm.shell.common.split.SplitScreenConstants.SPLIT_POSITION_TOP_OR_LEFT;
+import static com.android.wm.shell.common.split.SplitScreenConstants.SPLIT_POSITION_UNDEFINED;
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.transition.Transitions.ENABLE_SHELL_TRANSITIONS;
@@ -32,6 +34,7 @@
import android.app.ActivityTaskManager;
import android.app.PendingIntent;
import android.content.ActivityNotFoundException;
+import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.pm.LauncherApps;
@@ -68,6 +71,7 @@
import com.android.wm.shell.common.SyncTransactionQueue;
import com.android.wm.shell.common.TransactionPool;
import com.android.wm.shell.common.annotations.ExternalThread;
+import com.android.wm.shell.common.split.SplitLayout;
import com.android.wm.shell.common.split.SplitScreenConstants.SplitPosition;
import com.android.wm.shell.draganddrop.DragAndDropPolicy;
import com.android.wm.shell.recents.RecentTasksController;
@@ -196,11 +200,12 @@
@Nullable
public ActivityManager.RunningTaskInfo getTaskInfo(@SplitPosition int splitPosition) {
- if (isSplitScreenVisible()) {
- int taskId = mStageCoordinator.getTaskId(splitPosition);
- return mTaskOrganizer.getRunningTaskInfo(taskId);
+ if (!isSplitScreenVisible() || splitPosition == SPLIT_POSITION_UNDEFINED) {
+ return null;
}
- return null;
+
+ final int taskId = mStageCoordinator.getTaskId(splitPosition);
+ return mTaskOrganizer.getRunningTaskInfo(taskId);
}
public boolean isTaskInSplitScreen(int taskId) {
@@ -321,8 +326,8 @@
}
}
- public void startIntent(PendingIntent intent, Intent fillInIntent, @SplitPosition int position,
- @Nullable Bundle options) {
+ public void startIntent(PendingIntent intent, @Nullable Intent fillInIntent,
+ @SplitPosition int position, @Nullable Bundle options) {
if (!ENABLE_SHELL_TRANSITIONS) {
startIntentLegacy(intent, fillInIntent, position, options);
return;
@@ -331,6 +336,15 @@
try {
options = mStageCoordinator.resolveStartStage(STAGE_TYPE_UNDEFINED, position, options,
null /* wct */);
+
+ // Flag this as a no-user-action launch to prevent sending user leaving event to the
+ // current top activity since it's going to be put into another side of the split. This
+ // prevents the current top activity from going into pip mode due to user leaving event.
+ if (fillInIntent == null) {
+ fillInIntent = new Intent();
+ }
+ fillInIntent.addFlags(FLAG_ACTIVITY_NO_USER_ACTION);
+
intent.send(mContext, 0, fillInIntent, null /* onFinished */, null /* handler */,
null /* requiredPermission */, options);
} catch (PendingIntent.CanceledException e) {
@@ -338,7 +352,7 @@
}
}
- private void startIntentLegacy(PendingIntent intent, Intent fillInIntent,
+ private void startIntentLegacy(PendingIntent intent, @Nullable Intent fillInIntent,
@SplitPosition int position, @Nullable Bundle options) {
final WindowContainerTransaction evictWct = new WindowContainerTransaction();
mStageCoordinator.prepareEvictChildTasks(position, evictWct);
@@ -350,6 +364,18 @@
IRemoteAnimationFinishedCallback finishedCallback,
SurfaceControl.Transaction t) {
if (apps == null || apps.length == 0) {
+ final ActivityManager.RunningTaskInfo pairedTaskInfo =
+ getTaskInfo(SplitLayout.reversePosition(position));
+ final ComponentName pairedActivity =
+ pairedTaskInfo != null ? pairedTaskInfo.baseActivity : null;
+ final ComponentName intentActivity =
+ intent.getIntent() != null ? intent.getIntent().getComponent() : null;
+ if (pairedActivity != null && pairedActivity.equals(intentActivity)) {
+ // Switch split position if dragging the same activity to another side.
+ setSideStagePosition(SplitLayout.reversePosition(
+ mStageCoordinator.getSideStagePosition()));
+ }
+
// Do nothing when the animation was cancelled.
t.apply();
return;
@@ -377,6 +403,15 @@
final WindowContainerTransaction wct = new WindowContainerTransaction();
options = mStageCoordinator.resolveStartStage(STAGE_TYPE_UNDEFINED, position, options, wct);
+
+ // Flag this as a no-user-action launch to prevent sending user leaving event to the current
+ // top activity since it's going to be put into another side of the split. This prevents the
+ // current top activity from going into pip mode due to user leaving event.
+ if (fillInIntent == null) {
+ fillInIntent = new Intent();
+ }
+ fillInIntent.addFlags(FLAG_ACTIVITY_NO_USER_ACTION);
+
wct.sendPendingIntent(intent, fillInIntent, options);
mSyncQueue.queue(transition, WindowManager.TRANSIT_OPEN, wct);
}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageCoordinator.java b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageCoordinator.java
index 48dd1fe..ec1ddf0 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageCoordinator.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageCoordinator.java
@@ -29,6 +29,7 @@
import static android.view.WindowManager.TRANSIT_TO_FRONT;
import static android.view.WindowManager.transitTypeToString;
import static android.view.WindowManagerPolicyConstants.SPLIT_DIVIDER_LAYER;
+import static android.window.TransitionInfo.FLAG_IS_DISPLAY;
import static com.android.wm.shell.common.split.SplitScreenConstants.SPLIT_POSITION_BOTTOM_OR_RIGHT;
import static com.android.wm.shell.common.split.SplitScreenConstants.SPLIT_POSITION_TOP_OR_LEFT;
@@ -1171,6 +1172,8 @@
updateUnfoldBounds();
return;
}
+
+ mSplitLayout.update(null /* t */);
onLayoutSizeChanged(mSplitLayout);
}
}
@@ -1198,7 +1201,6 @@
if (!ENABLE_SHELL_TRANSITIONS) return;
final SurfaceControl.Transaction t = mTransactionPool.acquire();
- setDividerVisibility(false, t);
mDisplayLayout.rotateTo(mContext.getResources(), toRotation);
mSplitLayout.rotateTo(toRotation, mDisplayLayout.stableInsets());
updateWindowBounds(mSplitLayout, wct);
@@ -1255,8 +1257,15 @@
@Nullable TransitionRequestInfo request) {
final ActivityManager.RunningTaskInfo triggerTask = request.getTriggerTask();
if (triggerTask == null) {
- // Still want to monitor everything while in split-screen, so return non-null.
- return mMainStage.isActive() ? new WindowContainerTransaction() : null;
+ if (mMainStage.isActive()) {
+ if (request.getType() == TRANSIT_CHANGE && request.getDisplayChange() != null) {
+ mSplitLayout.setFreezeDividerWindow(true);
+ }
+ // Still want to monitor everything while in split-screen, so return non-null.
+ return new WindowContainerTransaction();
+ } else {
+ return null;
+ }
} else if (triggerTask.displayId != mDisplayId) {
// Skip handling task on the other display.
return null;
@@ -1352,8 +1361,14 @@
// If we're not in split-mode, just abort so something else can handle it.
if (!mMainStage.isActive()) return false;
+ mSplitLayout.setFreezeDividerWindow(false);
for (int iC = 0; iC < info.getChanges().size(); ++iC) {
final TransitionInfo.Change change = info.getChanges().get(iC);
+ if (change.getMode() == TRANSIT_CHANGE
+ && (change.getFlags() & FLAG_IS_DISPLAY) != 0) {
+ mSplitLayout.update(startTransaction);
+ }
+
final ActivityManager.RunningTaskInfo taskInfo = change.getTaskInfo();
if (taskInfo == null || !taskInfo.hasParentTask()) continue;
final StageTaskListener stage = getStageOfTask(taskInfo);
@@ -1368,10 +1383,6 @@
Log.w(TAG, "Expected onTaskVanished on " + stage + " to have been called"
+ " with " + taskInfo.taskId + " before startAnimation().");
}
- } else if (info.getType() == TRANSIT_CHANGE
- && change.getStartRotation() != change.getEndRotation()) {
- // Show the divider after transition finished.
- setDividerVisibility(true, finishTransaction);
}
}
if (mMainStage.getChildCount() == 0 || mSideStage.getChildCount() == 0) {
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/TaskSnapshotWindow.java b/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/TaskSnapshotWindow.java
index 1bef552e..49f907b 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/TaskSnapshotWindow.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/TaskSnapshotWindow.java
@@ -62,6 +62,7 @@
import android.graphics.Rect;
import android.graphics.RectF;
import android.hardware.HardwareBuffer;
+import android.os.Bundle;
import android.os.IBinder;
import android.os.RemoteException;
import android.os.Trace;
@@ -243,7 +244,7 @@
Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "TaskSnapshot#relayout");
session.relayout(window, layoutParams, -1, -1, View.VISIBLE, 0,
tmpFrames, tmpMergedConfiguration, surfaceControl, tmpInsetsState,
- tmpControls);
+ tmpControls, new Bundle());
Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
} catch (RemoteException e) {
snapshotSurface.clearWindowSynced();
@@ -517,7 +518,7 @@
private void reportDrawn() {
try {
- mSession.finishDrawing(mWindow, null /* postDrawTransaction */);
+ mSession.finishDrawing(mWindow, null /* postDrawTransaction */, Integer.MAX_VALUE);
} catch (RemoteException e) {
clearWindowSynced();
}
@@ -534,7 +535,7 @@
@Override
public void resized(ClientWindowFrames frames, boolean reportDraw,
MergedConfiguration mergedConfiguration, boolean forceLayout,
- boolean alwaysConsumeSystemBars, int displayId) {
+ boolean alwaysConsumeSystemBars, int displayId, int seqId) {
if (mOuter != null) {
mOuter.mSplashScreenExecutor.execute(() -> {
if (mergedConfiguration != null
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 a225f4e..2aa63b3 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
@@ -189,7 +189,7 @@
}
private void updateEnterpriseThumbnailDrawable() {
- mEnterpriseThumbnailDrawable = mDevicePolicyManager.getDrawable(
+ mEnterpriseThumbnailDrawable = mDevicePolicyManager.getResources().getDrawable(
WORK_PROFILE_ICON, OUTLINE, PROFILE_SWITCH_ANIMATION,
() -> mContext.getDrawable(R.drawable.ic_corp_badge));
}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/transition/Transitions.java b/libs/WindowManager/Shell/src/com/android/wm/shell/transition/Transitions.java
index fb3cd87..435d670 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/transition/Transitions.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/transition/Transitions.java
@@ -109,6 +109,9 @@
/** List of possible handlers. Ordered by specificity (eg. tapped back to front). */
private final ArrayList<TransitionHandler> mHandlers = new ArrayList<>();
+ /** List of {@link Runnable} instances to run when the last active transition has finished. */
+ private final ArrayList<Runnable> mRunWhenIdleQueue = new ArrayList<>();
+
private float mTransitionAnimationScaleSetting = 1.0f;
private static final class ActiveTransition {
@@ -224,6 +227,21 @@
mRemoteTransitionHandler.removeFiltered(remoteTransition);
}
+ /**
+ * Runs the given {@code runnable} when the last active transition has finished, or immediately
+ * if there are currently no active transitions.
+ *
+ * <p>This method should be called on the Shell main-thread, where the given {@code runnable}
+ * will be executed when the last active transition is finished.
+ */
+ public void runOnIdle(Runnable runnable) {
+ if (mActiveTransitions.isEmpty()) {
+ runnable.run();
+ } else {
+ mRunWhenIdleQueue.add(runnable);
+ }
+ }
+
/** @return true if the transition was triggered by opening something vs closing something */
public static boolean isOpeningType(@WindowManager.TransitionType int type) {
return type == TRANSIT_OPEN
@@ -520,6 +538,11 @@
if (mActiveTransitions.size() <= activeIdx) {
ProtoLog.v(ShellProtoLogGroup.WM_SHELL_TRANSITIONS, "All active transition animations "
+ "finished");
+ // Run all runnables from the run-when-idle queue.
+ for (int i = 0; i < mRunWhenIdleQueue.size(); i++) {
+ mRunWhenIdleQueue.get(i).run();
+ }
+ mRunWhenIdleQueue.clear();
return;
}
// Start animating the next active transition
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/back/BackAnimationControllerTest.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/back/BackAnimationControllerTest.java
index 9054685..3e7ee25 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/back/BackAnimationControllerTest.java
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/back/BackAnimationControllerTest.java
@@ -78,6 +78,7 @@
MockitoAnnotations.initMocks(this);
mController = new BackAnimationController(
mShellExecutor, mTransaction, mActivityTaskManager, mContext);
+ mController.setEnableAnimations(true);
}
private void createNavigationInfo(RemoteAnimationTarget topAnimationTarget,
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/common/split/SplitWindowManagerTests.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/common/split/SplitWindowManagerTests.java
index 9bb54a1..2e5078d 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/common/split/SplitWindowManagerTests.java
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/common/split/SplitWindowManagerTests.java
@@ -61,7 +61,7 @@
public void testInitRelease() {
mSplitWindowManager.init(mSplitLayout, new InsetsState());
assertThat(mSplitWindowManager.getSurfaceControl()).isNotNull();
- mSplitWindowManager.release();
+ mSplitWindowManager.release(null /* t */);
assertThat(mSplitWindowManager.getSurfaceControl()).isNull();
}
}
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/compatui/CompatUIControllerTest.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/compatui/CompatUIControllerTest.java
index a31b287..4607d8a 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/compatui/CompatUIControllerTest.java
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/compatui/CompatUIControllerTest.java
@@ -53,6 +53,7 @@
import com.android.wm.shell.common.ShellExecutor;
import com.android.wm.shell.common.SyncTransactionQueue;
import com.android.wm.shell.compatui.letterboxedu.LetterboxEduWindowManager;
+import com.android.wm.shell.transition.Transitions;
import org.junit.Before;
import org.junit.Test;
@@ -62,6 +63,8 @@
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
+import dagger.Lazy;
+
/**
* Tests for {@link CompatUIController}.
*
@@ -82,6 +85,7 @@
private @Mock ShellTaskOrganizer.TaskListener mMockTaskListener;
private @Mock SyncTransactionQueue mMockSyncQueue;
private @Mock ShellExecutor mMockExecutor;
+ private @Mock Lazy<Transitions> mMockTransitionsLazy;
private @Mock CompatUIWindowManager mMockCompatLayout;
private @Mock LetterboxEduWindowManager mMockLetterboxEduLayout;
@@ -102,7 +106,8 @@
doReturn(true).when(mMockLetterboxEduLayout).createLayout(anyBoolean());
doReturn(true).when(mMockLetterboxEduLayout).updateCompatInfo(any(), any(), anyBoolean());
mController = new CompatUIController(mContext, mMockDisplayController,
- mMockDisplayInsetsController, mMockImeController, mMockSyncQueue, mMockExecutor) {
+ mMockDisplayInsetsController, mMockImeController, mMockSyncQueue, mMockExecutor,
+ mMockTransitionsLazy) {
@Override
CompatUIWindowManager createCompatUiWindowManager(Context context, TaskInfo taskInfo,
ShellTaskOrganizer.TaskListener taskListener) {
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/compatui/letterboxedu/LetterboxEduWindowManagerTest.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/compatui/letterboxedu/LetterboxEduWindowManagerTest.java
index 337b738..7d51b52 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/compatui/letterboxedu/LetterboxEduWindowManagerTest.java
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/compatui/letterboxedu/LetterboxEduWindowManagerTest.java
@@ -54,6 +54,7 @@
import com.android.wm.shell.ShellTestCase;
import com.android.wm.shell.common.DisplayLayout;
import com.android.wm.shell.common.SyncTransactionQueue;
+import com.android.wm.shell.transition.Transitions;
import org.junit.After;
import org.junit.Before;
@@ -86,11 +87,14 @@
private ArgumentCaptor<WindowManager.LayoutParams> mWindowAttrsCaptor;
@Captor
private ArgumentCaptor<Runnable> mEndCallbackCaptor;
+ @Captor
+ private ArgumentCaptor<Runnable> mRunOnIdleCaptor;
@Mock private LetterboxEduAnimationController mAnimationController;
@Mock private SyncTransactionQueue mSyncTransactionQueue;
@Mock private ShellTaskOrganizer.TaskListener mTaskListener;
@Mock private SurfaceControlViewHost mViewHost;
+ @Mock private Transitions mTransitions;
@Mock private Runnable mOnDismissCallback;
private SharedPreferences mSharedPreferences;
@@ -204,6 +208,23 @@
}
@Test
+ public void testCreateLayout_windowManagerReleasedBeforeTransitionsIsIdle_doesNotStartAnim() {
+ LetterboxEduWindowManager windowManager = createWindowManager(/* eligible= */ true);
+
+ assertTrue(windowManager.createLayout(/* canShow= */ true));
+
+ assertTrue(mSharedPreferences.getBoolean(mPrefKey, /* default= */ false));
+
+ verify(mTransitions).runOnIdle(mRunOnIdleCaptor.capture());
+
+ windowManager.release();
+
+ mRunOnIdleCaptor.getValue().run();
+
+ verify(mAnimationController, never()).startEnterAnimation(any(), any());
+ }
+
+ @Test
public void testUpdateCompatInfo_updatesLayoutCorrectly() {
LetterboxEduWindowManager windowManager = createWindowManager(/* eligible= */ true);
@@ -303,6 +324,13 @@
}
private void verifyAndFinishEnterAnimation(LetterboxEduDialogLayout layout) {
+ verify(mTransitions).runOnIdle(mRunOnIdleCaptor.capture());
+
+ // startEnterAnimation isn't called until run-on-idle runnable is called.
+ verify(mAnimationController, never()).startEnterAnimation(any(), any());
+
+ mRunOnIdleCaptor.getValue().run();
+
verify(mAnimationController).startEnterAnimation(eq(layout), mEndCallbackCaptor.capture());
mEndCallbackCaptor.getValue().run();
}
@@ -320,7 +348,8 @@
boolean isTaskbarEduShowing) {
LetterboxEduWindowManager windowManager = new LetterboxEduWindowManager(mContext,
createTaskInfo(eligible), mSyncTransactionQueue, mTaskListener,
- createDisplayLayout(), mOnDismissCallback, mAnimationController);
+ createDisplayLayout(), mTransitions, mOnDismissCallback,
+ mAnimationController);
spyOn(windowManager);
doReturn(mViewHost).when(windowManager).createSurfaceViewHost();
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/kidsmode/KidsModeTaskOrganizerTest.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/kidsmode/KidsModeTaskOrganizerTest.java
index 78903dc..ff6dfdb 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/kidsmode/KidsModeTaskOrganizerTest.java
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/kidsmode/KidsModeTaskOrganizerTest.java
@@ -49,7 +49,6 @@
import com.android.wm.shell.common.DisplayInsetsController;
import com.android.wm.shell.common.ShellExecutor;
import com.android.wm.shell.common.SyncTransactionQueue;
-import com.android.wm.shell.compatui.CompatUIController;
import com.android.wm.shell.startingsurface.StartingWindowController;
import org.junit.Before;
@@ -67,7 +66,6 @@
@Mock private ITaskOrganizerController mTaskOrganizerController;
@Mock private Context mContext;
@Mock private Handler mHandler;
- @Mock private CompatUIController mCompatUI;
@Mock private SyncTransactionQueue mSyncTransactionQueue;
@Mock private ShellExecutor mTestExecutor;
@Mock private DisplayController mDisplayController;
@@ -86,9 +84,11 @@
try {
doReturn(ParceledListSlice.<TaskAppearedInfo>emptyList())
.when(mTaskOrganizerController).registerTaskOrganizer(any());
- } catch (RemoteException e) { }
+ } catch (RemoteException e) {
+ }
+ // NOTE: KidsModeTaskOrganizer should have a null CompatUIController.
mOrganizer = spy(new KidsModeTaskOrganizer(mTaskOrganizerController, mTestExecutor,
- mHandler, mContext, mCompatUI, mSyncTransactionQueue, mDisplayController,
+ mHandler, mContext, mSyncTransactionQueue, mDisplayController,
mDisplayInsetsController, Optional.empty(), mObserver));
mOrganizer.initialize(mStartingWindowController);
doReturn(mTransaction).when(mOrganizer).getWindowContainerTransaction();
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/transition/ShellTransitionTests.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/transition/ShellTransitionTests.java
index dbf93b4..a0b1297 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/transition/ShellTransitionTests.java
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/transition/ShellTransitionTests.java
@@ -46,6 +46,7 @@
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.ArgumentMatchers.isNull;
+import static org.mockito.Mockito.clearInvocations;
import static org.mockito.Mockito.doAnswer;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.times;
@@ -93,7 +94,7 @@
* Tests for the shell transitions.
*
* Build/Install/Run:
- * atest WMShellUnitTests:ShellTransitionTests
+ * atest WMShellUnitTests:ShellTransitionTests
*/
@SmallTest
@RunWith(AndroidJUnit4.class)
@@ -600,6 +601,83 @@
assertTrue(DefaultTransitionHandler.isRotationSeamless(seamlessDisplay, displays));
}
+ @Test
+ public void testRunWhenIdle() {
+ Transitions transitions = createTestTransitions();
+ transitions.replaceDefaultHandlerForTest(mDefaultHandler);
+
+ Runnable runnable1 = mock(Runnable.class);
+ Runnable runnable2 = mock(Runnable.class);
+ Runnable runnable3 = mock(Runnable.class);
+ Runnable runnable4 = mock(Runnable.class);
+
+ transitions.runOnIdle(runnable1);
+
+ // runnable1 is executed immediately because there are no active transitions.
+ verify(runnable1, times(1)).run();
+
+ clearInvocations(runnable1);
+
+ IBinder transitToken1 = new Binder();
+ transitions.requestStartTransition(transitToken1,
+ new TransitionRequestInfo(TRANSIT_OPEN, null /* trigger */, null /* remote */));
+ TransitionInfo info1 = new TransitionInfoBuilder(TRANSIT_OPEN)
+ .addChange(TRANSIT_OPEN).addChange(TRANSIT_CLOSE).build();
+ transitions.onTransitionReady(transitToken1, info1, mock(SurfaceControl.Transaction.class),
+ mock(SurfaceControl.Transaction.class));
+ assertEquals(1, mDefaultHandler.activeCount());
+
+ transitions.runOnIdle(runnable2);
+ transitions.runOnIdle(runnable3);
+
+ // runnable2 and runnable3 aren't executed immediately because there is an active
+ // transaction.
+
+ IBinder transitToken2 = new Binder();
+ transitions.requestStartTransition(transitToken2,
+ new TransitionRequestInfo(TRANSIT_CLOSE, null /* trigger */, null /* remote */));
+ TransitionInfo info2 = new TransitionInfoBuilder(TRANSIT_CLOSE)
+ .addChange(TRANSIT_OPEN).addChange(TRANSIT_CLOSE).build();
+ transitions.onTransitionReady(transitToken2, info2, mock(SurfaceControl.Transaction.class),
+ mock(SurfaceControl.Transaction.class));
+ assertEquals(1, mDefaultHandler.activeCount());
+
+ mDefaultHandler.finishAll();
+ mMainExecutor.flushAll();
+ // first transition finished
+ verify(mOrganizer, times(1)).finishTransition(eq(transitToken1), any(), any());
+ verify(mOrganizer, times(0)).finishTransition(eq(transitToken2), any(), any());
+ // But now the "queued" transition is running
+ assertEquals(1, mDefaultHandler.activeCount());
+
+ // runnable2 and runnable3 are still not executed because the second transition is still
+ // active.
+ verify(runnable2, times(0)).run();
+ verify(runnable3, times(0)).run();
+
+ mDefaultHandler.finishAll();
+ mMainExecutor.flushAll();
+ verify(mOrganizer, times(1)).finishTransition(eq(transitToken2), any(), any());
+
+ // runnable2 and runnable3 are executed after the second transition finishes because there
+ // are no other active transitions, runnable1 isn't executed again.
+ verify(runnable1, times(0)).run();
+ verify(runnable2, times(1)).run();
+ verify(runnable3, times(1)).run();
+
+ clearInvocations(runnable2);
+ clearInvocations(runnable3);
+
+ transitions.runOnIdle(runnable4);
+
+ // runnable4 is executed immediately because there are no active transitions, all other
+ // runnables aren't executed again.
+ verify(runnable1, times(0)).run();
+ verify(runnable2, times(0)).run();
+ verify(runnable3, times(0)).run();
+ verify(runnable4, times(1)).run();
+ }
+
class TransitionInfoBuilder {
final TransitionInfo mInfo;
@@ -749,7 +827,7 @@
IWindowManager mockWM = mock(IWindowManager.class);
final IDisplayWindowListener[] displayListener = new IDisplayWindowListener[1];
try {
- doReturn(new int[] {DEFAULT_DISPLAY}).when(mockWM).registerDisplayWindowListener(any());
+ doReturn(new int[]{DEFAULT_DISPLAY}).when(mockWM).registerDisplayWindowListener(any());
} catch (RemoteException e) {
// No remote stuff happening, so this can't be hit
}
diff --git a/libs/androidfw/Android.bp b/libs/androidfw/Android.bp
index 63b831d..c80fb18 100644
--- a/libs/androidfw/Android.bp
+++ b/libs/androidfw/Android.bp
@@ -118,7 +118,7 @@
"libz",
],
},
- linux_glibc: {
+ host_linux: {
srcs: [
"CursorWindow.cpp",
],
diff --git a/libs/hwui/HardwareBitmapUploader.cpp b/libs/hwui/HardwareBitmapUploader.cpp
index dd272cd..c24cabb 100644
--- a/libs/hwui/HardwareBitmapUploader.cpp
+++ b/libs/hwui/HardwareBitmapUploader.cpp
@@ -310,6 +310,11 @@
return has101012Support;
}
+bool HardwareBitmapUploader::hasAlpha8Support() {
+ static bool hasAlpha8Support = checkSupport(AHARDWAREBUFFER_FORMAT_R8_UNORM);
+ return hasAlpha8Support;
+}
+
static FormatInfo determineFormat(const SkBitmap& skBitmap, bool usingGL) {
FormatInfo formatInfo;
switch (skBitmap.info().colorType()) {
@@ -363,6 +368,13 @@
}
formatInfo.format = GL_RGBA;
break;
+ case kAlpha_8_SkColorType:
+ formatInfo.isSupported = HardwareBitmapUploader::hasAlpha8Support();
+ formatInfo.bufferFormat = AHARDWAREBUFFER_FORMAT_R8_UNORM;
+ formatInfo.format = GL_R8;
+ formatInfo.type = GL_UNSIGNED_BYTE;
+ formatInfo.vkFormat = VK_FORMAT_R8_UNORM;
+ break;
default:
ALOGW("unable to create hardware bitmap of colortype: %d", skBitmap.info().colorType());
formatInfo.valid = false;
diff --git a/libs/hwui/HardwareBitmapUploader.h b/libs/hwui/HardwareBitmapUploader.h
index 34f43cd..81057a2 100644
--- a/libs/hwui/HardwareBitmapUploader.h
+++ b/libs/hwui/HardwareBitmapUploader.h
@@ -30,11 +30,13 @@
#ifdef __ANDROID__
static bool hasFP16Support();
static bool has1010102Support();
+ static bool hasAlpha8Support();
#else
static bool hasFP16Support() {
return true;
}
static bool has1010102Support() { return true; }
+ static bool hasAlpha8Support() { return true; }
#endif
};
diff --git a/libs/hwui/Properties.cpp b/libs/hwui/Properties.cpp
index bcfe9c3..30ca7d15 100644
--- a/libs/hwui/Properties.cpp
+++ b/libs/hwui/Properties.cpp
@@ -135,7 +135,7 @@
skpCaptureEnabled = debuggingEnabled && base::GetBoolProperty(PROPERTY_CAPTURE_SKP_ENABLED, false);
SkAndroidFrameworkTraceUtil::setEnableTracing(
- base::GetBoolProperty(PROPERTY_SKIA_ATRACE_ENABLED, false));
+ base::GetBoolProperty(PROPERTY_SKIA_ATRACE_ENABLED, true));
runningInEmulator = base::GetBoolProperty(PROPERTY_IS_EMULATOR, false);
diff --git a/libs/hwui/hwui/Bitmap.cpp b/libs/hwui/hwui/Bitmap.cpp
index 1a89cfd..67f4758 100644
--- a/libs/hwui/hwui/Bitmap.cpp
+++ b/libs/hwui/hwui/Bitmap.cpp
@@ -104,6 +104,10 @@
sk_sp<Bitmap> Bitmap::allocateHardwareBitmap(const SkBitmap& bitmap) {
#ifdef __ANDROID__ // Layoutlib does not support hardware acceleration
+ if (bitmap.colorType() == kAlpha_8_SkColorType &&
+ !uirenderer::HardwareBitmapUploader::hasAlpha8Support()) {
+ return nullptr;
+ }
return uirenderer::HardwareBitmapUploader::allocateHardwareBitmap(bitmap);
#else
return Bitmap::allocateHeapBitmap(bitmap.info());
diff --git a/libs/hwui/renderthread/DrawFrameTask.cpp b/libs/hwui/renderthread/DrawFrameTask.cpp
index 8c98c72..2357dfe 100644
--- a/libs/hwui/renderthread/DrawFrameTask.cpp
+++ b/libs/hwui/renderthread/DrawFrameTask.cpp
@@ -133,6 +133,7 @@
}
void DrawFrameTask::postAndWait() {
+ ATRACE_CALL();
AutoMutex _lock(mLock);
mRenderThread->queue().post([this]() { run(); });
mSignal.wait(mLock);
diff --git a/libs/storage/IMountService.cpp b/libs/storage/IMountService.cpp
index 055dbb2..99508a2 100644
--- a/libs/storage/IMountService.cpp
+++ b/libs/storage/IMountService.cpp
@@ -48,8 +48,6 @@
TRANSACTION_isObbMounted,
TRANSACTION_getMountedObbPath,
TRANSACTION_isExternalStorageEmulated,
- TRANSACTION_decryptStorage,
- TRANSACTION_encryptStorage,
};
class BpMountService: public BpInterface<IMountService>
@@ -517,40 +515,6 @@
path = reply.readString16();
return true;
}
-
- int32_t decryptStorage(const String16& password)
- {
- Parcel data, reply;
- data.writeInterfaceToken(IMountService::getInterfaceDescriptor());
- data.writeString16(password);
- if (remote()->transact(TRANSACTION_decryptStorage, data, &reply) != NO_ERROR) {
- ALOGD("decryptStorage could not contact remote\n");
- return -1;
- }
- int32_t err = reply.readExceptionCode();
- if (err < 0) {
- ALOGD("decryptStorage caught exception %d\n", err);
- return err;
- }
- return reply.readInt32();
- }
-
- int32_t encryptStorage(const String16& password)
- {
- Parcel data, reply;
- data.writeInterfaceToken(IMountService::getInterfaceDescriptor());
- data.writeString16(password);
- if (remote()->transact(TRANSACTION_encryptStorage, data, &reply) != NO_ERROR) {
- ALOGD("encryptStorage could not contact remote\n");
- return -1;
- }
- int32_t err = reply.readExceptionCode();
- if (err < 0) {
- ALOGD("encryptStorage caught exception %d\n", err);
- return err;
- }
- return reply.readInt32();
- }
};
IMPLEMENT_META_INTERFACE(MountService, "android.os.storage.IStorageManager")
diff --git a/libs/storage/include/storage/IMountService.h b/libs/storage/include/storage/IMountService.h
index 5b07318..5a9c39b 100644
--- a/libs/storage/include/storage/IMountService.h
+++ b/libs/storage/include/storage/IMountService.h
@@ -70,8 +70,6 @@
const sp<IObbActionListener>& token, const int32_t nonce) = 0;
virtual bool isObbMounted(const String16& filename) = 0;
virtual bool getMountedObbPath(const String16& filename, String16& path) = 0;
- virtual int32_t decryptStorage(const String16& password) = 0;
- virtual int32_t encryptStorage(const String16& password) = 0;
};
// ----------------------------------------------------------------------------
diff --git a/location/java/android/location/GnssExcessPathInfo.java b/location/java/android/location/GnssExcessPathInfo.java
new file mode 100644
index 0000000..72b2374
--- /dev/null
+++ b/location/java/android/location/GnssExcessPathInfo.java
@@ -0,0 +1,375 @@
+/*
+ * 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.location;
+
+import static android.hardware.gnss.measurement_corrections.SingleSatCorrection.ExcessPathInfo.EXCESS_PATH_INFO_HAS_ATTENUATION;
+import static android.hardware.gnss.measurement_corrections.SingleSatCorrection.ExcessPathInfo.EXCESS_PATH_INFO_HAS_EXCESS_PATH_LENGTH;
+import static android.hardware.gnss.measurement_corrections.SingleSatCorrection.ExcessPathInfo.EXCESS_PATH_INFO_HAS_EXCESS_PATH_LENGTH_UNC;
+import static android.hardware.gnss.measurement_corrections.SingleSatCorrection.ExcessPathInfo.EXCESS_PATH_INFO_HAS_REFLECTING_PLANE;
+
+import android.annotation.FloatRange;
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.annotation.SystemApi;
+import android.os.Parcel;
+import android.os.Parcelable;
+
+import com.android.internal.util.Preconditions;
+
+import java.util.Objects;
+
+/**
+ * Contains the info of an excess path signal caused by reflection
+ *
+ * @hide
+ */
+@SystemApi
+public final class GnssExcessPathInfo implements Parcelable {
+
+ private static final int HAS_EXCESS_PATH_LENGTH_MASK = EXCESS_PATH_INFO_HAS_EXCESS_PATH_LENGTH;
+ private static final int HAS_EXCESS_PATH_LENGTH_UNC_MASK =
+ EXCESS_PATH_INFO_HAS_EXCESS_PATH_LENGTH_UNC;
+ private static final int HAS_REFLECTING_PLANE_MASK = EXCESS_PATH_INFO_HAS_REFLECTING_PLANE;
+ private static final int HAS_ATTENUATION_MASK = EXCESS_PATH_INFO_HAS_ATTENUATION;
+
+ /* A bitmask of fields present in this object (see HAS_* constants defined above) */
+ private final int mFlags;
+ private final float mExcessPathLengthMeters;
+ private final float mExcessPathLengthUncertaintyMeters;
+ @Nullable
+ private final GnssReflectingPlane mReflectingPlane;
+ private final float mAttenuationDb;
+
+ private GnssExcessPathInfo(
+ int flags,
+ float excessPathLengthMeters,
+ float excessPathLengthUncertaintyMeters,
+ @Nullable GnssReflectingPlane reflectingPlane,
+ float attenuationDb) {
+ mFlags = flags;
+ mExcessPathLengthMeters = excessPathLengthMeters;
+ mExcessPathLengthUncertaintyMeters = excessPathLengthUncertaintyMeters;
+ mReflectingPlane = reflectingPlane;
+ mAttenuationDb = attenuationDb;
+ }
+
+ /**
+ * Gets a bitmask of fields present in this object.
+ *
+ * <p>This API exists for JNI since it is easier for JNI to get one integer flag than looking up
+ * several has* methods.
+ * @hide
+ */
+ public int getFlags() {
+ return mFlags;
+ }
+
+ /** Returns {@code true} if {@link #getExcessPathLengthMeters()} is valid. */
+ public boolean hasExcessPathLength() {
+ return (mFlags & HAS_EXCESS_PATH_LENGTH_MASK) != 0;
+ }
+
+ /**
+ * Returns the excess path length to be subtracted from pseudorange before using it in
+ * calculating location.
+ *
+ * <p>{@link #hasExcessPathLength()} must be true when calling this method. Otherwise, an
+ * {@link UnsupportedOperationException} will be thrown.
+ */
+ @FloatRange(from = 0.0f)
+ public float getExcessPathLengthMeters() {
+ if (!hasExcessPathLength()) {
+ throw new UnsupportedOperationException(
+ "getExcessPathLengthMeters() is not supported when hasExcessPathLength() is "
+ + "false");
+ }
+ return mExcessPathLengthMeters;
+ }
+
+ /** Returns {@code true} if {@link #getExcessPathLengthUncertaintyMeters()} is valid. */
+ public boolean hasExcessPathLengthUncertainty() {
+ return (mFlags & HAS_EXCESS_PATH_LENGTH_UNC_MASK) != 0;
+ }
+
+ /**
+ * Returns the error estimate (1-sigma) for the excess path length estimate.
+ *
+ * <p>{@link #hasExcessPathLengthUncertainty()} must be true when calling this method.
+ * Otherwise, an {@link UnsupportedOperationException} will be thrown.
+ */
+ @FloatRange(from = 0.0f)
+ public float getExcessPathLengthUncertaintyMeters() {
+ if (!hasExcessPathLengthUncertainty()) {
+ throw new UnsupportedOperationException(
+ "getExcessPathLengthUncertaintyMeters() is not supported when "
+ + "hasExcessPathLengthUncertainty() is false");
+ }
+ return mExcessPathLengthUncertaintyMeters;
+ }
+
+ /**
+ * Returns {@code true} if {@link #getReflectingPlane()} is valid.
+ *
+ * <p>Returns false if the satellite signal goes through multiple reflections or if reflection
+ * plane serving is not supported.
+ */
+ public boolean hasReflectingPlane() {
+ return (mFlags & HAS_REFLECTING_PLANE_MASK) != 0;
+ }
+
+ /**
+ * Returns the reflecting plane characteristics at which the signal has bounced.
+ *
+ * <p>{@link #hasReflectingPlane()} must be true when calling this method. Otherwise, an
+ * {@link UnsupportedOperationException} will be thrown.
+ */
+ @NonNull
+ public GnssReflectingPlane getReflectingPlane() {
+ if (!hasReflectingPlane()) {
+ throw new UnsupportedOperationException(
+ "getReflectingPlane() is not supported when hasReflectingPlane() is false");
+ }
+ return mReflectingPlane;
+ }
+
+ /** Returns {@code true} if {@link #getAttenuationDb()} is valid. */
+ public boolean hasAttenuation() {
+ return (mFlags & HAS_ATTENUATION_MASK) != 0;
+ }
+
+ /**
+ * Returns the expected reduction of signal strength of this path in non-negative dB.
+ *
+ * <p>{@link #hasAttenuation()} must be true when calling this method. Otherwise, an
+ * {@link UnsupportedOperationException} will be thrown.
+ */
+ @FloatRange(from = 0.0f)
+ public float getAttenuationDb() {
+ if (!hasAttenuation()) {
+ throw new UnsupportedOperationException(
+ "getAttenuationDb() is not supported when hasAttenuation() is false");
+ }
+ return mAttenuationDb;
+ }
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ @Override
+ public void writeToParcel(@NonNull Parcel parcel, int parcelFlags) {
+ parcel.writeInt(mFlags);
+ if (hasExcessPathLength()) {
+ parcel.writeFloat(mExcessPathLengthMeters);
+ }
+ if (hasExcessPathLengthUncertainty()) {
+ parcel.writeFloat(mExcessPathLengthUncertaintyMeters);
+ }
+ if (hasReflectingPlane()) {
+ mReflectingPlane.writeToParcel(parcel, parcelFlags);
+ }
+ if (hasAttenuation()) {
+ parcel.writeFloat(mAttenuationDb);
+ }
+ }
+
+ public static final @NonNull Creator<GnssExcessPathInfo> CREATOR =
+ new Creator<GnssExcessPathInfo>() {
+ @Override
+ @NonNull
+ public GnssExcessPathInfo createFromParcel(@NonNull Parcel parcel) {
+ int flags = parcel.readInt();
+ float excessPathLengthMeters =
+ (flags & HAS_EXCESS_PATH_LENGTH_MASK) != 0
+ ? parcel.readFloat() : 0;
+ float excessPathLengthUncertaintyMeters =
+ (flags & HAS_EXCESS_PATH_LENGTH_UNC_MASK) != 0
+ ? parcel.readFloat() : 0;
+ GnssReflectingPlane reflectingPlane =
+ (flags & HAS_REFLECTING_PLANE_MASK) != 0
+ ? GnssReflectingPlane.CREATOR.createFromParcel(parcel) : null;
+ float attenuationDb =
+ (flags & HAS_ATTENUATION_MASK) != 0
+ ? parcel.readFloat() : 0;
+ return new GnssExcessPathInfo(flags, excessPathLengthMeters,
+ excessPathLengthUncertaintyMeters, reflectingPlane, attenuationDb);
+ }
+
+ @Override
+ public GnssExcessPathInfo[] newArray(int i) {
+ return new GnssExcessPathInfo[i];
+ }
+ };
+
+ @Override
+ public boolean equals(Object obj) {
+ if (obj instanceof GnssExcessPathInfo) {
+ GnssExcessPathInfo that = (GnssExcessPathInfo) obj;
+ return this.mFlags == that.mFlags
+ && (!hasExcessPathLength() || Float.compare(this.mExcessPathLengthMeters,
+ that.mExcessPathLengthMeters) == 0)
+ && (!hasExcessPathLengthUncertainty() || Float.compare(
+ this.mExcessPathLengthUncertaintyMeters,
+ that.mExcessPathLengthUncertaintyMeters) == 0)
+ && (!hasReflectingPlane() || Objects.equals(this.mReflectingPlane,
+ that.mReflectingPlane))
+ && (!hasAttenuation() || Float.compare(this.mAttenuationDb,
+ that.mAttenuationDb) == 0);
+ }
+ return false;
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(mFlags,
+ mExcessPathLengthMeters,
+ mExcessPathLengthUncertaintyMeters,
+ mReflectingPlane,
+ mAttenuationDb);
+ }
+
+ @NonNull
+ @Override
+ public String toString() {
+ StringBuilder builder = new StringBuilder("GnssExcessPathInfo[");
+ if (hasExcessPathLength()) {
+ builder.append(" ExcessPathLengthMeters=").append(mExcessPathLengthMeters);
+ }
+ if (hasExcessPathLengthUncertainty()) {
+ builder.append(" ExcessPathLengthUncertaintyMeters=").append(
+ mExcessPathLengthUncertaintyMeters);
+ }
+ if (hasReflectingPlane()) {
+ builder.append(" ReflectingPlane=").append(mReflectingPlane);
+ }
+ if (hasAttenuation()) {
+ builder.append(" AttenuationDb=").append(mAttenuationDb);
+ }
+ builder.append(']');
+ return builder.toString();
+ }
+
+ /** Builder for {@link GnssExcessPathInfo}. */
+ public static final class Builder {
+ private int mFlags;
+ private float mExcessPathLengthMeters;
+ private float mExcessPathLengthUncertaintyMeters;
+ @Nullable
+ private GnssReflectingPlane mReflectingPlane;
+ private float mAttenuationDb;
+
+ /** Constructor for {@link Builder}. */
+ public Builder() {}
+
+ /**
+ * Sets the excess path length to be subtracted from pseudorange before using it in
+ * calculating location.
+ */
+ @NonNull
+ public Builder setExcessPathLengthMeters(
+ @FloatRange(from = 0.0f) float excessPathLengthMeters) {
+ Preconditions.checkArgumentInRange(excessPathLengthMeters, 0, Float.MAX_VALUE,
+ "excessPathLengthMeters");
+ mExcessPathLengthMeters = excessPathLengthMeters;
+ mFlags |= HAS_EXCESS_PATH_LENGTH_MASK;
+ return this;
+ }
+
+ /**
+ * Clears the excess path length.
+ *
+ * <p>This is to negate {@link #setExcessPathLengthMeters} call.
+ */
+ @NonNull
+ public Builder clearExcessPathLengthMeters() {
+ mExcessPathLengthMeters = 0;
+ mFlags &= ~HAS_EXCESS_PATH_LENGTH_MASK;
+ return this;
+ }
+
+ /** Sets the error estimate (1-sigma) for the excess path length estimate */
+ @NonNull
+ public Builder setExcessPathLengthUncertaintyMeters(
+ @FloatRange(from = 0.0f) float excessPathLengthUncertaintyMeters) {
+ Preconditions.checkArgumentInRange(excessPathLengthUncertaintyMeters, 0,
+ Float.MAX_VALUE, "excessPathLengthUncertaintyMeters");
+ mExcessPathLengthUncertaintyMeters = excessPathLengthUncertaintyMeters;
+ mFlags |= HAS_EXCESS_PATH_LENGTH_UNC_MASK;
+ return this;
+ }
+
+ /**
+ * Clears the error estimate (1-sigma) for the excess path length estimate
+ *
+ * <p>This is to negate {@link #setExcessPathLengthUncertaintyMeters} call.
+ */
+ @NonNull
+ public Builder clearExcessPathLengthUncertaintyMeters() {
+ mExcessPathLengthUncertaintyMeters = 0;
+ mFlags &= ~HAS_EXCESS_PATH_LENGTH_UNC_MASK;
+ return this;
+ }
+
+ /** Sets the reflecting plane information */
+ @NonNull
+ public Builder setReflectingPlane(@Nullable GnssReflectingPlane reflectingPlane) {
+ mReflectingPlane = reflectingPlane;
+ if (reflectingPlane != null) {
+ mFlags |= HAS_REFLECTING_PLANE_MASK;
+ } else {
+ mFlags &= ~HAS_REFLECTING_PLANE_MASK;
+ }
+ return this;
+ }
+
+ /**
+ * Sets the attenuation value in dB.
+ */
+ @NonNull
+ public Builder setAttenuationDb(@FloatRange(from = 0.0f) float attenuationDb) {
+ Preconditions.checkArgumentInRange(attenuationDb, 0, Float.MAX_VALUE,
+ "attenuationDb");
+ mAttenuationDb = attenuationDb;
+ mFlags |= HAS_ATTENUATION_MASK;
+ return this;
+ }
+
+ /**
+ * Clears the attenuation value in dB.
+ *
+ * <p>This is to negate {@link #setAttenuationDb(float)} call.
+ */
+ @NonNull
+ public Builder clearAttenuationDb() {
+ mAttenuationDb = 0;
+ mFlags &= ~HAS_ATTENUATION_MASK;
+ return this;
+ }
+
+ /** Builds a {@link GnssExcessPathInfo} instance as specified by this builder. */
+ @NonNull
+ public GnssExcessPathInfo build() {
+ return new GnssExcessPathInfo(
+ mFlags,
+ mExcessPathLengthMeters,
+ mExcessPathLengthUncertaintyMeters,
+ mReflectingPlane,
+ mAttenuationDb);
+ }
+ }
+}
diff --git a/location/java/android/location/GnssReflectingPlane.java b/location/java/android/location/GnssReflectingPlane.java
index 1acdd1e..115cbec 100644
--- a/location/java/android/location/GnssReflectingPlane.java
+++ b/location/java/android/location/GnssReflectingPlane.java
@@ -22,9 +22,14 @@
import android.os.Parcel;
import android.os.Parcelable;
+import java.util.Objects;
+
/**
* Holds the characteristics of the reflecting plane that a satellite signal has bounced from.
*
+ * <p>Starting with Android T, this class supports {@link #equals} and {@link #hashCode}, which
+ * are not supported before that.
+ *
* @hide
*/
@SystemApi
@@ -107,18 +112,6 @@
}
};
- @NonNull
- @Override
- public String toString() {
- final String format = " %-29s = %s\n";
- StringBuilder builder = new StringBuilder("ReflectingPlane:\n");
- builder.append(String.format(format, "LatitudeDegrees = ", mLatitudeDegrees));
- builder.append(String.format(format, "LongitudeDegrees = ", mLongitudeDegrees));
- builder.append(String.format(format, "AltitudeMeters = ", mAltitudeMeters));
- builder.append(String.format(format, "AzimuthDegrees = ", mAzimuthDegrees));
- return builder.toString();
- }
-
@Override
public void writeToParcel(@NonNull Parcel parcel, int flags) {
parcel.writeDouble(mLatitudeDegrees);
@@ -127,6 +120,35 @@
parcel.writeDouble(mAzimuthDegrees);
}
+ @NonNull
+ @Override
+ public String toString() {
+ StringBuilder builder = new StringBuilder("ReflectingPlane[");
+ builder.append(" LatitudeDegrees=").append(mLatitudeDegrees);
+ builder.append(" LongitudeDegrees=").append(mLongitudeDegrees);
+ builder.append(" AltitudeMeters=").append(mAltitudeMeters);
+ builder.append(" AzimuthDegrees=").append(mAzimuthDegrees);
+ builder.append(']');
+ return builder.toString();
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (obj instanceof GnssReflectingPlane) {
+ GnssReflectingPlane that = (GnssReflectingPlane) obj;
+ return Double.compare(this.mLatitudeDegrees, that.mLatitudeDegrees) == 0
+ && Double.compare(this.mLongitudeDegrees, that.mLongitudeDegrees) == 0
+ && Double.compare(this.mAltitudeMeters, that.mAltitudeMeters) == 0
+ && Double.compare(this.mAzimuthDegrees, that.mAzimuthDegrees) == 0;
+ }
+ return false;
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(mLatitudeDegrees, mLatitudeDegrees, mAltitudeMeters, mAzimuthDegrees);
+ }
+
/** Builder for {@link GnssReflectingPlane} */
public static final class Builder {
/** For documentation, see corresponding fields in {@link GnssReflectingPlane}. */
diff --git a/location/java/android/location/GnssSingleSatCorrection.java b/location/java/android/location/GnssSingleSatCorrection.java
index 262630b..a7fce0a 100644
--- a/location/java/android/location/GnssSingleSatCorrection.java
+++ b/location/java/android/location/GnssSingleSatCorrection.java
@@ -16,6 +16,11 @@
package android.location;
+import static android.hardware.gnss.measurement_corrections.SingleSatCorrection.SINGLE_SAT_CORRECTION_HAS_COMBINED_ATTENUATION;
+import static android.hardware.gnss.measurement_corrections.SingleSatCorrection.SINGLE_SAT_CORRECTION_HAS_COMBINED_EXCESS_PATH_LENGTH;
+import static android.hardware.gnss.measurement_corrections.SingleSatCorrection.SINGLE_SAT_CORRECTION_HAS_COMBINED_EXCESS_PATH_LENGTH_UNC;
+import static android.hardware.gnss.measurement_corrections.SingleSatCorrection.SINGLE_SAT_CORRECTION_HAS_SAT_IS_LOS_PROBABILITY;
+
import android.annotation.FloatRange;
import android.annotation.IntRange;
import android.annotation.NonNull;
@@ -26,6 +31,8 @@
import com.android.internal.util.Preconditions;
+import java.util.ArrayList;
+import java.util.List;
import java.util.Objects;
/**
@@ -36,106 +43,47 @@
@SystemApi
public final class GnssSingleSatCorrection implements Parcelable {
- /**
- * Bit mask for {@link #mSingleSatCorrectionFlags} indicating the presence of {@link
- * #mProbSatIsLos}.
- *
- * @hide
- */
- public static final int HAS_PROB_SAT_IS_LOS_MASK = 1 << 0;
+ private static final int HAS_PROB_SAT_IS_LOS_MASK =
+ SINGLE_SAT_CORRECTION_HAS_SAT_IS_LOS_PROBABILITY;
+ private static final int HAS_COMBINED_EXCESS_PATH_LENGTH_MASK =
+ SINGLE_SAT_CORRECTION_HAS_COMBINED_EXCESS_PATH_LENGTH;
+ private static final int HAS_COMBINED_EXCESS_PATH_LENGTH_UNC_MASK =
+ SINGLE_SAT_CORRECTION_HAS_COMBINED_EXCESS_PATH_LENGTH_UNC;
+ private static final int HAS_COMBINED_ATTENUATION_MASK =
+ SINGLE_SAT_CORRECTION_HAS_COMBINED_ATTENUATION;
- /**
- * Bit mask for {@link #mSingleSatCorrectionFlags} indicating the presence of {@link
- * #mExcessPathLengthMeters}.
- *
- * @hide
- */
- public static final int HAS_EXCESS_PATH_LENGTH_MASK = 1 << 1;
-
- /**
- * Bit mask for {@link #mSingleSatCorrectionFlags} indicating the presence of {@link
- * #mExcessPathLengthUncertaintyMeters}.
- *
- * @hide
- */
- public static final int HAS_EXCESS_PATH_LENGTH_UNC_MASK = 1 << 2;
-
- /**
- * Bit mask for {@link #mSingleSatCorrectionFlags} indicating the presence of {@link
- * #mReflectingPlane}.
- *
- * @hide
- */
- public static final int HAS_REFLECTING_PLANE_MASK = 1 << 3;
-
- /** A bitmask of fields present in this object (see HAS_* constants defined above) */
+ /* A bitmask of fields present in this object (see HAS_* constants defined above). */
private final int mSingleSatCorrectionFlags;
- /** Defines the constellation of the given satellite as defined in {@link GnssStatus}. */
- @GnssStatus.ConstellationType
private final int mConstellationType;
-
- /**
- * Satellite vehicle ID number
- *
- * <p>Interpretation depends on {@link GnssStatus#getSvid(int)}.
- */
- @IntRange(from = 0)
private final int mSatId;
-
- /**
- * Carrier frequency of the signal to be corrected, for example it can be the GPS center
- * frequency for L1 = 1,575,420,000 Hz, varying GLO channels, etc.
- *
- * <p>For an L1, L5 receiver tracking a satellite on L1 and L5 at the same time, two correction
- * objects will be reported for this same satellite, in one of the correction objects, all the
- * values related to L1 will be filled, and in the other all of the values related to L5 will be
- * filled.
- */
- @FloatRange(from = 0.0f, fromInclusive = false)
private final float mCarrierFrequencyHz;
-
- /**
- * The probability that the satellite is estimated to be in Line-of-Sight condition at the given
- * location.
- */
- @FloatRange(from = 0.0f, to = 1.0f)
private final float mProbSatIsLos;
+ private final float mCombinedExcessPathLengthMeters;
+ private final float mCombinedExcessPathLengthUncertaintyMeters;
+ private final float mCombinedAttenuationDb;
- /**
- * Excess path length to be subtracted from pseudorange before using it in calculating location.
- */
- @FloatRange(from = 0.0f)
- private final float mExcessPathLengthMeters;
-
- /** Error estimate (1-sigma) for the Excess path length estimate */
- @FloatRange(from = 0.0f)
- private final float mExcessPathLengthUncertaintyMeters;
-
- /**
- * Defines the reflecting plane location and azimuth information
- *
- * <p>The flag HAS_REFLECTING_PLANE will be used to set this value to invalid if the satellite
- * signal goes through multiple reflections or if reflection plane serving is not supported.
- */
- @Nullable
- private final GnssReflectingPlane mReflectingPlane;
+ @NonNull
+ private final List<GnssExcessPathInfo> mGnssExcessPathInfoList;
private GnssSingleSatCorrection(int singleSatCorrectionFlags, int constellationType, int satId,
float carrierFrequencyHz, float probSatIsLos, float excessPathLengthMeters,
- float excessPathLengthUncertaintyMeters, GnssReflectingPlane reflectingPlane) {
+ float excessPathLengthUncertaintyMeters,
+ float combinedAttenuationDb,
+ @NonNull List<GnssExcessPathInfo> gnssExcessPathInfoList) {
mSingleSatCorrectionFlags = singleSatCorrectionFlags;
mConstellationType = constellationType;
mSatId = satId;
mCarrierFrequencyHz = carrierFrequencyHz;
mProbSatIsLos = probSatIsLos;
- mExcessPathLengthMeters = excessPathLengthMeters;
- mExcessPathLengthUncertaintyMeters = excessPathLengthUncertaintyMeters;
- mReflectingPlane = reflectingPlane;
+ mCombinedExcessPathLengthMeters = excessPathLengthMeters;
+ mCombinedExcessPathLengthUncertaintyMeters = excessPathLengthUncertaintyMeters;
+ mCombinedAttenuationDb = combinedAttenuationDb;
+ mGnssExcessPathInfoList = gnssExcessPathInfoList;
}
/**
- * Gets a bitmask of fields present in this object
+ * Gets a bitmask of fields present in this object.
*
* @hide
*/
@@ -193,29 +141,46 @@
}
/**
- * Returns the Excess path length to be subtracted from pseudorange before using it in
+ * Returns the combined excess path length to be subtracted from pseudorange before using it in
* calculating location.
*/
@FloatRange(from = 0.0f)
public float getExcessPathLengthMeters() {
- return mExcessPathLengthMeters;
+ return mCombinedExcessPathLengthMeters;
}
- /** Returns the error estimate (1-sigma) for the Excess path length estimate */
+ /** Returns the error estimate (1-sigma) for the combined excess path length estimate. */
@FloatRange(from = 0.0f)
public float getExcessPathLengthUncertaintyMeters() {
- return mExcessPathLengthUncertaintyMeters;
+ return mCombinedExcessPathLengthUncertaintyMeters;
}
/**
- * Returns the reflecting plane characteristics at which the signal has bounced
+ * Returns the combined expected reduction of signal strength for this satellite in
+ * non-negative dB.
+ */
+ @FloatRange(from = 0.0f)
+ public float getCombinedAttenuationDb() {
+ return mCombinedAttenuationDb;
+ }
+
+ /**
+ * Returns the reflecting plane characteristics at which the signal has bounced.
*
- * <p>The flag HAS_REFLECTING_PLANE will be used to set this value to invalid if the satellite
- * signal goes through multiple reflections or if reflection plane serving is not supported
+ * @deprecated Combined excess path does not have a reflecting plane.
*/
@Nullable
+ @Deprecated
public GnssReflectingPlane getReflectingPlane() {
- return mReflectingPlane;
+ return null;
+ }
+
+ /**
+ * Returns the list of {@link GnssExcessPathInfo} associated with this satellite signal.
+ */
+ @NonNull
+ public List<GnssExcessPathInfo> getGnssExcessPathInfoList() {
+ return mGnssExcessPathInfoList;
}
/** Returns {@code true} if {@link #getProbabilityLineOfSight()} is valid. */
@@ -225,17 +190,27 @@
/** Returns {@code true} if {@link #getExcessPathLengthMeters()} is valid. */
public boolean hasExcessPathLength() {
- return (mSingleSatCorrectionFlags & HAS_EXCESS_PATH_LENGTH_MASK) != 0;
+ return (mSingleSatCorrectionFlags & HAS_COMBINED_EXCESS_PATH_LENGTH_MASK) != 0;
}
/** Returns {@code true} if {@link #getExcessPathLengthUncertaintyMeters()} is valid. */
public boolean hasExcessPathLengthUncertainty() {
- return (mSingleSatCorrectionFlags & HAS_EXCESS_PATH_LENGTH_UNC_MASK) != 0;
+ return (mSingleSatCorrectionFlags & HAS_COMBINED_EXCESS_PATH_LENGTH_UNC_MASK) != 0;
}
- /** Returns {@code true} if {@link #getReflectingPlane()} is valid. */
+ /**
+ * Returns {@code true} if {@link #getReflectingPlane()} is valid.
+ *
+ * @deprecated Combined excess path does not have a reflecting plane.
+ */
+ @Deprecated
public boolean hasReflectingPlane() {
- return (mSingleSatCorrectionFlags & HAS_REFLECTING_PLANE_MASK) != 0;
+ return false;
+ }
+
+ /** Returns {@code true} if {@link #getCombinedAttenuationDb()} is valid. */
+ public boolean hasCombinedAttenuation() {
+ return (mSingleSatCorrectionFlags & HAS_COMBINED_ATTENUATION_MASK) != 0;
}
@Override
@@ -253,14 +228,15 @@
parcel.writeFloat(mProbSatIsLos);
}
if (hasExcessPathLength()) {
- parcel.writeFloat(mExcessPathLengthMeters);
+ parcel.writeFloat(mCombinedExcessPathLengthMeters);
}
if (hasExcessPathLengthUncertainty()) {
- parcel.writeFloat(mExcessPathLengthUncertaintyMeters);
+ parcel.writeFloat(mCombinedExcessPathLengthUncertaintyMeters);
}
- if (hasReflectingPlane()) {
- mReflectingPlane.writeToParcel(parcel, flags);
+ if (hasCombinedAttenuation()) {
+ parcel.writeFloat(mCombinedAttenuationDb);
}
+ parcel.writeTypedList(mGnssExcessPathInfoList);
}
public static final Creator<GnssSingleSatCorrection> CREATOR =
@@ -274,18 +250,21 @@
float carrierFrequencyHz = parcel.readFloat();
float probSatIsLos = (singleSatCorrectionFlags & HAS_PROB_SAT_IS_LOS_MASK) != 0
? parcel.readFloat() : 0;
- float excessPathLengthMeters =
- (singleSatCorrectionFlags & HAS_EXCESS_PATH_LENGTH_MASK) != 0
+ float combinedExcessPathLengthMeters =
+ (singleSatCorrectionFlags & HAS_COMBINED_EXCESS_PATH_LENGTH_MASK) != 0
? parcel.readFloat() : 0;
- float excessPathLengthUncertaintyMeters =
- (singleSatCorrectionFlags & HAS_EXCESS_PATH_LENGTH_UNC_MASK) != 0
+ float combinedExcessPathLengthUncertaintyMeters =
+ (singleSatCorrectionFlags & HAS_COMBINED_EXCESS_PATH_LENGTH_UNC_MASK)
+ != 0 ? parcel.readFloat() : 0;
+ float combinedAttenuationDb =
+ (singleSatCorrectionFlags & HAS_COMBINED_ATTENUATION_MASK) != 0
? parcel.readFloat() : 0;
- GnssReflectingPlane reflectingPlane =
- (singleSatCorrectionFlags & HAS_REFLECTING_PLANE_MASK) != 0
- ? GnssReflectingPlane.CREATOR.createFromParcel(parcel) : null;
+ List<GnssExcessPathInfo> gnssExcessPathInfoList = parcel.createTypedArrayList(
+ GnssExcessPathInfo.CREATOR);
return new GnssSingleSatCorrection(singleSatCorrectionFlags, constellationType,
- satId, carrierFrequencyHz, probSatIsLos, excessPathLengthMeters,
- excessPathLengthUncertaintyMeters, reflectingPlane);
+ satId, carrierFrequencyHz, probSatIsLos, combinedExcessPathLengthMeters,
+ combinedExcessPathLengthUncertaintyMeters, combinedAttenuationDb,
+ gnssExcessPathInfoList);
}
@Override
@@ -296,56 +275,24 @@
@Override
public boolean equals(Object obj) {
- if (this == obj) {
- return true;
+ if (obj instanceof GnssSingleSatCorrection) {
+ GnssSingleSatCorrection that = (GnssSingleSatCorrection) obj;
+ return this.mSingleSatCorrectionFlags == that.mSingleSatCorrectionFlags
+ && this.mConstellationType == that.mConstellationType
+ && this.mSatId == that.mSatId
+ && Float.compare(mCarrierFrequencyHz, that.mCarrierFrequencyHz) == 0
+ && (!hasValidSatelliteLineOfSight() || Float.compare(mProbSatIsLos,
+ that.mProbSatIsLos) == 0)
+ && (!hasExcessPathLength() || Float.compare(mCombinedExcessPathLengthMeters,
+ that.mCombinedExcessPathLengthMeters) == 0)
+ && (!hasExcessPathLengthUncertainty() || Float.compare(
+ mCombinedExcessPathLengthUncertaintyMeters,
+ that.mCombinedExcessPathLengthUncertaintyMeters) == 0)
+ && (!hasCombinedAttenuation() || Float.compare(mCombinedAttenuationDb,
+ that.mCombinedAttenuationDb) == 0)
+ && mGnssExcessPathInfoList.equals(that.mGnssExcessPathInfoList);
}
- if (!(obj instanceof GnssSingleSatCorrection)) {
- return false;
- }
-
- GnssSingleSatCorrection other = (GnssSingleSatCorrection) obj;
- if (mConstellationType != other.mConstellationType) {
- return false;
- }
- if (mSatId != other.mSatId) {
- return false;
- }
- if (Float.compare(mCarrierFrequencyHz, other.mCarrierFrequencyHz) != 0) {
- return false;
- }
-
- if (hasValidSatelliteLineOfSight() != other.hasValidSatelliteLineOfSight()) {
- return false;
- }
- if (hasValidSatelliteLineOfSight()
- && Float.compare(mProbSatIsLos, other.mProbSatIsLos) != 0) {
- return false;
- }
-
- if (hasExcessPathLength() != other.hasExcessPathLength()) {
- return false;
- }
- if (hasExcessPathLength()
- && Float.compare(mExcessPathLengthMeters, other.mExcessPathLengthMeters) != 0) {
- return false;
- }
-
- if (hasExcessPathLengthUncertainty() != other.hasExcessPathLengthUncertainty()) {
- return false;
- }
- if (hasExcessPathLengthUncertainty() && Float.compare(mExcessPathLengthUncertaintyMeters,
- other.mExcessPathLengthUncertaintyMeters) != 0) {
- return false;
- }
-
- if (hasReflectingPlane() != other.hasReflectingPlane()) {
- return false;
- }
- if (hasReflectingPlane()
- && !mReflectingPlane.equals(other.mReflectingPlane)) {
- return false;
- }
- return true;
+ return false;
}
@Override
@@ -355,9 +302,10 @@
mSatId,
mCarrierFrequencyHz,
mProbSatIsLos,
- mExcessPathLengthMeters,
- mExcessPathLengthUncertaintyMeters,
- mReflectingPlane);
+ mCombinedExcessPathLengthMeters,
+ mCombinedExcessPathLengthUncertaintyMeters,
+ mCombinedAttenuationDb,
+ mGnssExcessPathInfoList);
}
@NonNull
@@ -371,14 +319,19 @@
builder.append(" ProbSatIsLos=").append(mProbSatIsLos);
}
if (hasExcessPathLength()) {
- builder.append(" ExcessPathLengthMeters=").append(mExcessPathLengthMeters);
+ builder.append(" CombinedExcessPathLengthMeters=").append(
+ mCombinedExcessPathLengthMeters);
}
if (hasExcessPathLengthUncertainty()) {
- builder.append(" ExcessPathLengthUncertaintyMeters=").append(
- mExcessPathLengthUncertaintyMeters);
+ builder.append(" CombinedExcessPathLengthUncertaintyMeters=").append(
+ mCombinedExcessPathLengthUncertaintyMeters);
}
- if (hasReflectingPlane()) {
- builder.append(" ReflectingPlane=").append(mReflectingPlane);
+ if (hasCombinedAttenuation()) {
+ builder.append(" CombinedAttenuationDb=").append(
+ mCombinedAttenuationDb);
+ }
+ if (!mGnssExcessPathInfoList.isEmpty()) {
+ builder.append(' ').append(mGnssExcessPathInfoList.toString());
}
builder.append(']');
return builder.toString();
@@ -386,21 +339,16 @@
/** Builder for {@link GnssSingleSatCorrection} */
public static final class Builder {
-
- /**
- * For documentation of below fields, see corresponding fields in {@link
- * GnssSingleSatCorrection}.
- */
private int mSingleSatCorrectionFlags;
-
private int mConstellationType;
private int mSatId;
private float mCarrierFrequencyHz;
private float mProbSatIsLos;
- private float mExcessPathLengthMeters;
- private float mExcessPathLengthUncertaintyMeters;
- @Nullable
- private GnssReflectingPlane mReflectingPlane;
+ private float mCombinedExcessPathLengthMeters;
+ private float mCombinedExcessPathLengthUncertaintyMeters;
+ private float mCombinedAttenuationDb;
+ @NonNull
+ private List<GnssExcessPathInfo> mGnssExcessInfoList = new ArrayList<>();
/** Sets the constellation type. */
@NonNull public Builder setConstellationType(
@@ -409,18 +357,18 @@
return this;
}
- /** Sets the Satellite ID defined in the ICD of the given constellation. */
+ /** Sets the satellite ID defined in the ICD of the given constellation. */
@NonNull public Builder setSatelliteId(@IntRange(from = 0) int satId) {
Preconditions.checkArgumentNonnegative(satId, "satId should be non-negative.");
mSatId = satId;
return this;
}
- /** Sets the Carrier frequency in Hz. */
+ /** Sets the carrier frequency in Hz. */
@NonNull public Builder setCarrierFrequencyHz(
@FloatRange(from = 0.0f, fromInclusive = false) float carrierFrequencyHz) {
- Preconditions.checkArgument(
- carrierFrequencyHz >= 0, "carrierFrequencyHz should be non-negative.");
+ Preconditions.checkArgumentInRange(
+ carrierFrequencyHz, 0, Float.MAX_VALUE, "carrierFrequencyHz");
mCarrierFrequencyHz = carrierFrequencyHz;
return this;
}
@@ -450,58 +398,90 @@
}
/**
- * Sets the Excess path length to be subtracted from pseudorange before using it in
+ * Sets the combined excess path length to be subtracted from pseudorange before using it in
* calculating location.
*/
- @NonNull public Builder setExcessPathLengthMeters(
- @FloatRange(from = 0.0f) float excessPathLengthMeters) {
- Preconditions.checkArgument(excessPathLengthMeters >= 0,
- "excessPathLengthMeters should be non-negative.");
- mExcessPathLengthMeters = excessPathLengthMeters;
- mSingleSatCorrectionFlags |= HAS_EXCESS_PATH_LENGTH_MASK;
+ @NonNull
+ public Builder setExcessPathLengthMeters(
+ @FloatRange(from = 0.0f) float combinedExcessPathLengthMeters) {
+ Preconditions.checkArgumentInRange(combinedExcessPathLengthMeters, 0, Float.MAX_VALUE,
+ "excessPathLengthMeters");
+ mCombinedExcessPathLengthMeters = combinedExcessPathLengthMeters;
+ mSingleSatCorrectionFlags |= HAS_COMBINED_EXCESS_PATH_LENGTH_MASK;
return this;
}
/**
- * Clears the Excess path length.
+ * Clears the combined excess path length.
*
* <p>This is to negate {@link #setExcessPathLengthMeters} call.
*/
@NonNull public Builder clearExcessPathLengthMeters() {
- mExcessPathLengthMeters = 0;
- mSingleSatCorrectionFlags &= ~HAS_EXCESS_PATH_LENGTH_MASK;
+ mCombinedExcessPathLengthMeters = 0;
+ mSingleSatCorrectionFlags &= ~HAS_COMBINED_EXCESS_PATH_LENGTH_MASK;
return this;
}
- /** Sets the error estimate (1-sigma) for the Excess path length estimate */
+ /** Sets the error estimate (1-sigma) for the combined excess path length estimate. */
@NonNull public Builder setExcessPathLengthUncertaintyMeters(
- @FloatRange(from = 0.0f) float excessPathLengthUncertaintyMeters) {
- Preconditions.checkArgument(excessPathLengthUncertaintyMeters >= 0,
- "excessPathLengthUncertaintyMeters should be non-negative.");
- mExcessPathLengthUncertaintyMeters = excessPathLengthUncertaintyMeters;
- mSingleSatCorrectionFlags |= HAS_EXCESS_PATH_LENGTH_UNC_MASK;
+ @FloatRange(from = 0.0f) float combinedExcessPathLengthUncertaintyMeters) {
+ Preconditions.checkArgumentInRange(combinedExcessPathLengthUncertaintyMeters, 0,
+ Float.MAX_VALUE, "excessPathLengthUncertaintyMeters");
+ mCombinedExcessPathLengthUncertaintyMeters = combinedExcessPathLengthUncertaintyMeters;
+ mSingleSatCorrectionFlags |= HAS_COMBINED_EXCESS_PATH_LENGTH_UNC_MASK;
return this;
}
/**
- * Clears the error estimate (1-sigma) for the Excess path length estimate
+ * Clears the error estimate (1-sigma) for the combined excess path length estimate.
*
* <p>This is to negate {@link #setExcessPathLengthUncertaintyMeters} call.
*/
@NonNull public Builder clearExcessPathLengthUncertaintyMeters() {
- mExcessPathLengthUncertaintyMeters = 0;
- mSingleSatCorrectionFlags &= ~HAS_EXCESS_PATH_LENGTH_UNC_MASK;
+ mCombinedExcessPathLengthUncertaintyMeters = 0;
+ mSingleSatCorrectionFlags &= ~HAS_COMBINED_EXCESS_PATH_LENGTH_UNC_MASK;
return this;
}
- /** Sets the reflecting plane information */
+ /**
+ * Sets the combined attenuation in Db.
+ */
+ @NonNull public Builder setCombinedAttenuationDb(
+ @FloatRange(from = 0.0f) float combinedAttenuationDb) {
+ Preconditions.checkArgumentInRange(combinedAttenuationDb, 0, Float.MAX_VALUE,
+ "combinedAttenuationDb");
+ mCombinedAttenuationDb = combinedAttenuationDb;
+ mSingleSatCorrectionFlags |= HAS_COMBINED_ATTENUATION_MASK;
+ return this;
+ }
+
+ /**
+ * Clears the combined attenuation.
+ *
+ * <p>This is to negate {@link #setCombinedAttenuationDb} call.
+ */
+ @NonNull public Builder clearCombinedAttenuationDb() {
+ mCombinedAttenuationDb = 0;
+ mSingleSatCorrectionFlags &= ~HAS_COMBINED_ATTENUATION_MASK;
+ return this;
+ }
+
+ /**
+ * Sets the reflecting plane information.
+ *
+ * @deprecated Combined excess path does not have a reflecting plane.
+ */
+ @Deprecated
@NonNull public Builder setReflectingPlane(@Nullable GnssReflectingPlane reflectingPlane) {
- mReflectingPlane = reflectingPlane;
- if (reflectingPlane != null) {
- mSingleSatCorrectionFlags |= HAS_REFLECTING_PLANE_MASK;
- } else {
- mSingleSatCorrectionFlags &= ~HAS_REFLECTING_PLANE_MASK;
- }
+ return this;
+ }
+
+ /**
+ * Sets the collection of {@link GnssExcessPathInfo}.
+ */
+ @NonNull
+ public Builder setGnssExcessPathInfoList(@NonNull List<GnssExcessPathInfo> infoList) {
+ mGnssExcessInfoList = new ArrayList<>(infoList);
return this;
}
@@ -512,9 +492,10 @@
mSatId,
mCarrierFrequencyHz,
mProbSatIsLos,
- mExcessPathLengthMeters,
- mExcessPathLengthUncertaintyMeters,
- mReflectingPlane);
+ mCombinedExcessPathLengthMeters,
+ mCombinedExcessPathLengthUncertaintyMeters,
+ mCombinedAttenuationDb,
+ mGnssExcessInfoList);
}
}
}
diff --git a/location/java/android/location/LastLocationRequest.java b/location/java/android/location/LastLocationRequest.java
index fe0a14f..ec03a33 100644
--- a/location/java/android/location/LastLocationRequest.java
+++ b/location/java/android/location/LastLocationRequest.java
@@ -17,7 +17,6 @@
package android.location;
import static android.Manifest.permission.LOCATION_BYPASS;
-import static android.Manifest.permission.WRITE_SECURE_SETTINGS;
import android.Manifest;
import android.annotation.NonNull;
@@ -223,9 +222,8 @@
*
* @hide
*/
- // TODO: remove WRITE_SECURE_SETTINGS.
@SystemApi
- @RequiresPermission(anyOf = {WRITE_SECURE_SETTINGS, LOCATION_BYPASS})
+ @RequiresPermission(LOCATION_BYPASS)
public @NonNull LastLocationRequest.Builder setAdasGnssBypass(boolean adasGnssBypass) {
mAdasGnssBypass = adasGnssBypass;
return this;
@@ -242,9 +240,8 @@
*
* @hide
*/
- // TODO: remove WRITE_SECURE_SETTINGS.
@SystemApi
- @RequiresPermission(anyOf = {WRITE_SECURE_SETTINGS, LOCATION_BYPASS})
+ @RequiresPermission(LOCATION_BYPASS)
public @NonNull Builder setLocationSettingsIgnored(boolean locationSettingsIgnored) {
mLocationSettingsIgnored = locationSettingsIgnored;
return this;
diff --git a/location/java/android/location/Location.java b/location/java/android/location/Location.java
index f1605f1..033056c 100644
--- a/location/java/android/location/Location.java
+++ b/location/java/android/location/Location.java
@@ -132,31 +132,31 @@
}
/**
- * Construct a new Location object that is copied from an existing one.
+ * Constructs a new location copied from the given location.
*/
- public Location(@NonNull Location l) {
- set(l);
+ public Location(@NonNull Location location) {
+ set(location);
}
/**
* Turns this location into a copy of the given location.
*/
- public void set(@NonNull Location l) {
- mFieldsMask = l.mFieldsMask;
- mProvider = l.mProvider;
- mTimeMs = l.mTimeMs;
- mElapsedRealtimeNs = l.mElapsedRealtimeNs;
- mElapsedRealtimeUncertaintyNs = l.mElapsedRealtimeUncertaintyNs;
- mLatitudeDegrees = l.mLatitudeDegrees;
- mLongitudeDegrees = l.mLongitudeDegrees;
- mHorizontalAccuracyMeters = l.mHorizontalAccuracyMeters;
- mAltitudeMeters = l.mAltitudeMeters;
- mAltitudeAccuracyMeters = l.mAltitudeAccuracyMeters;
- mSpeedMetersPerSecond = l.mSpeedMetersPerSecond;
- mSpeedAccuracyMetersPerSecond = l.mSpeedAccuracyMetersPerSecond;
- mBearingDegrees = l.mBearingDegrees;
- mBearingAccuracyDegrees = l.mBearingAccuracyDegrees;
- mExtras = (l.mExtras == null) ? null : new Bundle(l.mExtras);
+ public void set(@NonNull Location location) {
+ mFieldsMask = location.mFieldsMask;
+ mProvider = location.mProvider;
+ mTimeMs = location.mTimeMs;
+ mElapsedRealtimeNs = location.mElapsedRealtimeNs;
+ mElapsedRealtimeUncertaintyNs = location.mElapsedRealtimeUncertaintyNs;
+ mLatitudeDegrees = location.mLatitudeDegrees;
+ mLongitudeDegrees = location.mLongitudeDegrees;
+ mHorizontalAccuracyMeters = location.mHorizontalAccuracyMeters;
+ mAltitudeMeters = location.mAltitudeMeters;
+ mAltitudeAccuracyMeters = location.mAltitudeAccuracyMeters;
+ mSpeedMetersPerSecond = location.mSpeedMetersPerSecond;
+ mSpeedAccuracyMetersPerSecond = location.mSpeedAccuracyMetersPerSecond;
+ mBearingDegrees = location.mBearingDegrees;
+ mBearingAccuracyDegrees = location.mBearingAccuracyDegrees;
+ mExtras = (location.mExtras == null) ? null : new Bundle(location.mExtras);
}
/**
@@ -182,14 +182,13 @@
}
/**
- * Returns the approximate distance in meters between this
- * location and the given location. Distance is defined using
- * the WGS84 ellipsoid.
+ * Returns the approximate distance in meters between this location and the given location.
+ * Distance is defined using the WGS84 ellipsoid.
*
* @param dest the destination location
* @return the approximate distance in meters
*/
- public @FloatRange float distanceTo(@NonNull Location dest) {
+ public @FloatRange(from = 0.0) float distanceTo(@NonNull Location dest) {
BearingDistanceCache cache = sBearingDistanceCache.get();
// See if we already have the result
if (mLatitudeDegrees != cache.mLat1 || mLongitudeDegrees != cache.mLon1
@@ -201,11 +200,10 @@
}
/**
- * Returns the approximate initial bearing in degrees East of true
- * North when traveling along the shortest path between this
- * location and the given location. The shortest path is defined
- * using the WGS84 ellipsoid. Locations that are (nearly)
- * antipodal may produce meaningless results.
+ * Returns the approximate initial bearing in degrees east of true north when traveling along
+ * the shortest path between this location and the given location. The shortest path is defined
+ * using the WGS84 ellipsoid. Locations that are (nearly) antipodal may produce meaningless
+ * results.
*
* @param dest the destination location
* @return the initial bearing in degrees
@@ -254,7 +252,7 @@
* not be used to order or compare locations. Prefer {@link #getElapsedRealtimeNanos} for that
* purpose, as the elapsed realtime clock is guaranteed to be monotonic.
*
- * <p>On the other hand, this method may be useful for presenting a human readable time to the
+ * <p>On the other hand, this method may be useful for presenting a human-readable time to the
* user, or as a heuristic for comparing location fixes across reboot or across devices.
*
* <p>All locations generated by the {@link LocationManager} are guaranteed to have this time
@@ -263,25 +261,24 @@
*
* @return the Unix epoch time of this location
*/
- public @IntRange long getTime() {
+ public @IntRange(from = 0) long getTime() {
return mTimeMs;
}
/**
* Sets the Unix epoch time of this location fix, in milliseconds since the start of the Unix
- * epoch (00:00:00 January 1, 1970 UTC).
+ * epoch (00:00:00 January 1 1970 UTC).
*
* @param timeMs the Unix epoch time of this location
- * @see #getTime for more information about times / clocks
*/
- public void setTime(@IntRange long timeMs) {
+ public void setTime(@IntRange(from = 0) long timeMs) {
mTimeMs = timeMs;
}
/**
* Return the time of this fix in nanoseconds of elapsed realtime since system boot.
*
- * <p>This value can be compared with {@link android.os.SystemClock#elapsedRealtimeNanos}, to
+ * <p>This value can be compared with {@link android.os.SystemClock#elapsedRealtimeNanos} to
* reliably order or compare locations. This is reliable because elapsed realtime is guaranteed
* to be monotonic and continues to increment even when the system is in deep sleep (unlike
* {@link #getTime}). However, since elapsed realtime is with reference to system boot, it does
@@ -292,7 +289,7 @@
*
* @return elapsed realtime of this location in nanoseconds
*/
- public @IntRange long getElapsedRealtimeNanos() {
+ public @IntRange(from = 0) long getElapsedRealtimeNanos() {
return mElapsedRealtimeNs;
}
@@ -302,7 +299,7 @@
* @return elapsed realtime of this location in milliseconds
* @see #getElapsedRealtimeNanos()
*/
- public @IntRange long getElapsedRealtimeMillis() {
+ public @IntRange(from = 0) long getElapsedRealtimeMillis() {
return NANOSECONDS.toMillis(mElapsedRealtimeNs);
}
@@ -312,7 +309,7 @@
*
* @return age of this location in milliseconds
*/
- public @IntRange long getElapsedRealtimeAgeMillis() {
+ public @IntRange(from = 0) long getElapsedRealtimeAgeMillis() {
return getElapsedRealtimeAgeMillis(SystemClock.elapsedRealtime());
}
@@ -323,7 +320,8 @@
* @param referenceRealtimeMs reference realtime in milliseconds
* @return age of this location in milliseconds
*/
- public @IntRange long getElapsedRealtimeAgeMillis(@IntRange long referenceRealtimeMs) {
+ public long getElapsedRealtimeAgeMillis(
+ @IntRange(from = 0) long referenceRealtimeMs) {
return referenceRealtimeMs - getElapsedRealtimeMillis();
}
@@ -332,7 +330,7 @@
*
* @param elapsedRealtimeNs elapsed realtime in nanoseconds
*/
- public void setElapsedRealtimeNanos(@IntRange long elapsedRealtimeNs) {
+ public void setElapsedRealtimeNanos(@IntRange(from = 0) long elapsedRealtimeNs) {
mElapsedRealtimeNs = elapsedRealtimeNs;
}
@@ -346,7 +344,7 @@
*
* @return uncertainty in nanoseconds of the elapsed realtime of this location
*/
- public @FloatRange double getElapsedRealtimeUncertaintyNanos() {
+ public @FloatRange(from = 0.0) double getElapsedRealtimeUncertaintyNanos() {
return mElapsedRealtimeUncertaintyNs;
}
@@ -358,20 +356,20 @@
* this location
*/
public void setElapsedRealtimeUncertaintyNanos(
- @FloatRange double elapsedRealtimeUncertaintyNs) {
+ @FloatRange(from = 0.0) double elapsedRealtimeUncertaintyNs) {
mElapsedRealtimeUncertaintyNs = elapsedRealtimeUncertaintyNs;
mFieldsMask |= HAS_ELAPSED_REALTIME_UNCERTAINTY_MASK;
}
/**
- * True if this location has a elapsed realtime uncertainty, false otherwise.
+ * True if this location has an elapsed realtime uncertainty, false otherwise.
*/
public boolean hasElapsedRealtimeUncertaintyNanos() {
return (mFieldsMask & HAS_ELAPSED_REALTIME_UNCERTAINTY_MASK) != 0;
}
/**
- * Removes the elapsed realtime uncertainy from this location.
+ * Removes the elapsed realtime uncertainty from this location.
*/
public void removeElapsedRealtimeUncertaintyNanos() {
mFieldsMask &= ~HAS_ELAPSED_REALTIME_UNCERTAINTY_MASK;
@@ -383,7 +381,7 @@
*
* @return latitude of this location
*/
- public @FloatRange double getLatitude() {
+ public @FloatRange(from = -90.0, to = 90.0) double getLatitude() {
return mLatitudeDegrees;
}
@@ -392,7 +390,7 @@
*
* @param latitudeDegrees latitude in degrees
*/
- public void setLatitude(@FloatRange double latitudeDegrees) {
+ public void setLatitude(@FloatRange(from = -90.0, to = 90.0) double latitudeDegrees) {
mLatitudeDegrees = latitudeDegrees;
}
@@ -402,7 +400,7 @@
*
* @return longitude of this location
*/
- public @FloatRange double getLongitude() {
+ public @FloatRange(from = -180.0, to = 180.0) double getLongitude() {
return mLongitudeDegrees;
}
@@ -411,7 +409,7 @@
*
* @param longitudeDegrees longitude in degrees
*/
- public void setLongitude(@FloatRange double longitudeDegrees) {
+ public void setLongitude(@FloatRange(from = -180.0, to = 180.0) double longitudeDegrees) {
mLongitudeDegrees = longitudeDegrees;
}
@@ -423,12 +421,12 @@
* reported location, there is a 68% chance that the true location falls within this circle.
* This accuracy value is only valid for horizontal positioning, and not vertical positioning.
*
- * <p>This is only valid if {@link #hasSpeed()} is true. All locations generated by the
+ * <p>This is only valid if {@link #hasAccuracy()} is true. All locations generated by the
* {@link LocationManager} include horizontal accuracy.
*
* @return horizontal accuracy of this location
*/
- public @FloatRange float getAccuracy() {
+ public @FloatRange(from = 0.0) float getAccuracy() {
return mHorizontalAccuracyMeters;
}
@@ -437,7 +435,7 @@
*
* @param horizontalAccuracyMeters horizontal altitude in meters
*/
- public void setAccuracy(@FloatRange float horizontalAccuracyMeters) {
+ public void setAccuracy(@FloatRange(from = 0.0) float horizontalAccuracyMeters) {
mHorizontalAccuracyMeters = horizontalAccuracyMeters;
mFieldsMask |= HAS_HORIZONTAL_ACCURACY_MASK;
}
@@ -500,7 +498,7 @@
*
* @return vertical accuracy of this location
*/
- public @FloatRange float getVerticalAccuracyMeters() {
+ public @FloatRange(from = 0.0) float getVerticalAccuracyMeters() {
return mAltitudeAccuracyMeters;
}
@@ -509,7 +507,7 @@
*
* @param altitudeAccuracyMeters altitude accuracy in meters
*/
- public void setVerticalAccuracyMeters(@FloatRange float altitudeAccuracyMeters) {
+ public void setVerticalAccuracyMeters(@FloatRange(from = 0.0) float altitudeAccuracyMeters) {
mAltitudeAccuracyMeters = altitudeAccuracyMeters;
mFieldsMask |= HAS_ALTITUDE_ACCURACY_MASK;
}
@@ -538,17 +536,16 @@
*
* @return speed at the time of this location
*/
- public @FloatRange float getSpeed() {
+ public @FloatRange(from = 0.0) float getSpeed() {
return mSpeedMetersPerSecond;
}
/**
- * Set the speed at the time of this location, in meters per second. Prefer not to set negative
- * speeds.
+ * Set the speed at the time of this location, in meters per second.
*
* @param speedMetersPerSecond speed in meters per second
*/
- public void setSpeed(@FloatRange float speedMetersPerSecond) {
+ public void setSpeed(@FloatRange(from = 0.0) float speedMetersPerSecond) {
mSpeedMetersPerSecond = speedMetersPerSecond;
mFieldsMask |= HAS_SPEED_MASK;
}
@@ -576,7 +573,7 @@
*
* @return vertical accuracy of this location
*/
- public @FloatRange float getSpeedAccuracyMetersPerSecond() {
+ public @FloatRange(from = 0.0) float getSpeedAccuracyMetersPerSecond() {
return mSpeedAccuracyMetersPerSecond;
}
@@ -585,7 +582,8 @@
*
* @param speedAccuracyMeterPerSecond speed accuracy in meters per second
*/
- public void setSpeedAccuracyMetersPerSecond(@FloatRange float speedAccuracyMeterPerSecond) {
+ public void setSpeedAccuracyMetersPerSecond(
+ @FloatRange(from = 0.0) float speedAccuracyMeterPerSecond) {
mSpeedAccuracyMetersPerSecond = speedAccuracyMeterPerSecond;
mFieldsMask |= HAS_SPEED_ACCURACY_MASK;
}
@@ -613,7 +611,7 @@
*
* @return bearing at the time of this location
*/
- public @FloatRange(from = 0f, to = 360f, toInclusive = false) float getBearing() {
+ public @FloatRange(from = 0.0, to = 360.0, toInclusive = false) float getBearing() {
return mBearingDegrees;
}
@@ -663,7 +661,7 @@
*
* @return bearing accuracy in degrees of this location
*/
- public @FloatRange float getBearingAccuracyDegrees() {
+ public @FloatRange(from = 0.0) float getBearingAccuracyDegrees() {
return mBearingAccuracyDegrees;
}
@@ -672,7 +670,7 @@
*
* @param bearingAccuracyDegrees bearing accuracy in degrees
*/
- public void setBearingAccuracyDegrees(@FloatRange float bearingAccuracyDegrees) {
+ public void setBearingAccuracyDegrees(@FloatRange(from = 0.0) float bearingAccuracyDegrees) {
mBearingAccuracyDegrees = bearingAccuracyDegrees;
mFieldsMask |= HAS_BEARING_ACCURACY_MASK;
}
@@ -692,9 +690,11 @@
}
/**
- * Returns true if the Location came from a mock provider.
+ * Returns true if this is a mock location. If this location comes from the Android framework,
+ * this indicates that the location was provided by a test location provider, and thus may not
+ * be related to the actual location of the device.
*
- * @return true if this Location came from a mock provider, false otherwise
+ * @return true if this location came from a mock provider, false otherwise
* @deprecated Prefer {@link #isMock()} instead.
*/
@Deprecated
@@ -703,9 +703,9 @@
}
/**
- * Flag this Location as having come from a mock provider or not.
+ * Flag this location as having come from a mock provider or not.
*
- * @param isFromMockProvider true if this Location came from a mock provider, false otherwise
+ * @param isFromMockProvider true if this location came from a mock provider, false otherwise
* @deprecated Prefer {@link #setMock(boolean)} instead.
* @hide
*/
@@ -745,7 +745,7 @@
* will be present for any location.
*
* <ul>
- * <li> satellites - the number of satellites used to derive the GNSS fix
+ * <li> satellites - the number of satellites used to derive a GNSS fix
* </ul>
*/
public @Nullable Bundle getExtras() {
@@ -899,7 +899,13 @@
return s.toString();
}
- /** Dumps location. */
+ /**
+ * Dumps location information to the given Printer.
+ *
+ * @deprecated Prefer to use {@link #toString()} along with whatever custom formatting is
+ * required instead of this method. It is not this class's job to manage print representations.
+ */
+ @Deprecated
public void dump(@NonNull Printer pw, @Nullable String prefix) {
pw.println(prefix + this);
}
@@ -1209,10 +1215,10 @@
* @throws IllegalArgumentException if results is null or has length < 1
*/
public static void distanceBetween(
- @FloatRange double startLatitude,
- @FloatRange double startLongitude,
- @FloatRange double endLatitude,
- @FloatRange double endLongitude,
+ @FloatRange(from = -90.0, to = 90.0) double startLatitude,
+ @FloatRange(from = -180.0, to = 180.0) double startLongitude,
+ @FloatRange(from = -90.0, to = 90.0) double endLatitude,
+ @FloatRange(from = -180.0, to = 180.0) double endLongitude,
float[] results) {
if (results == null || results.length < 1) {
throw new IllegalArgumentException("results is null or has length < 1");
diff --git a/location/java/android/location/LocationManager.java b/location/java/android/location/LocationManager.java
index 59c989b..a504cfe 100644
--- a/location/java/android/location/LocationManager.java
+++ b/location/java/android/location/LocationManager.java
@@ -679,9 +679,8 @@
*
* @hide
*/
- // TODO: remove WRITE_SECURE_SETTINGS.
@SystemApi
- @RequiresPermission(anyOf = {WRITE_SECURE_SETTINGS, LOCATION_BYPASS})
+ @RequiresPermission(LOCATION_BYPASS)
public void setAdasGnssLocationEnabled(boolean enabled) {
try {
mService.setAdasGnssLocationEnabledForUser(enabled, mContext.getUser().getIdentifier());
diff --git a/location/java/android/location/LocationRequest.java b/location/java/android/location/LocationRequest.java
index 59f4f5e..09474b5 100644
--- a/location/java/android/location/LocationRequest.java
+++ b/location/java/android/location/LocationRequest.java
@@ -17,7 +17,6 @@
package android.location;
import static android.Manifest.permission.LOCATION_BYPASS;
-import static android.Manifest.permission.WRITE_SECURE_SETTINGS;
import static java.lang.Math.max;
import static java.lang.Math.min;
@@ -665,10 +664,9 @@
* @hide
* @deprecated LocationRequests should be treated as immutable.
*/
- // TODO: remove WRITE_SECURE_SETTINGS.
@SystemApi
@Deprecated
- @RequiresPermission(anyOf = {WRITE_SECURE_SETTINGS, LOCATION_BYPASS})
+ @RequiresPermission(LOCATION_BYPASS)
public @NonNull LocationRequest setLocationSettingsIgnored(boolean locationSettingsIgnored) {
mBypass = locationSettingsIgnored;
return this;
@@ -1136,9 +1134,8 @@
*
* @hide
*/
- // TODO: remove WRITE_SECURE_SETTINGS
@SystemApi
- @RequiresPermission(anyOf = {WRITE_SECURE_SETTINGS, LOCATION_BYPASS})
+ @RequiresPermission(LOCATION_BYPASS)
public @NonNull Builder setAdasGnssBypass(boolean adasGnssBypass) {
mAdasGnssBypass = adasGnssBypass;
return this;
@@ -1155,9 +1152,8 @@
*
* @hide
*/
- // TODO: remove WRITE_SECURE_SETTINGS
@SystemApi
- @RequiresPermission(anyOf = {WRITE_SECURE_SETTINGS, LOCATION_BYPASS})
+ @RequiresPermission(LOCATION_BYPASS)
public @NonNull Builder setLocationSettingsIgnored(boolean locationSettingsIgnored) {
mBypass = locationSettingsIgnored;
return this;
diff --git a/media/java/android/media/IAudioService.aidl b/media/java/android/media/IAudioService.aidl
index bdbb740..c186700 100755
--- a/media/java/android/media/IAudioService.aidl
+++ b/media/java/android/media/IAudioService.aidl
@@ -39,6 +39,7 @@
import android.media.IRingtonePlayer;
import android.media.IStrategyPreferredDevicesDispatcher;
import android.media.ISpatializerCallback;
+import android.media.ISpatializerHeadTrackerAvailableCallback;
import android.media.ISpatializerHeadTrackingModeCallback;
import android.media.ISpatializerHeadToSoundStagePoseCallback;
import android.media.ISpatializerOutputCallback;
@@ -414,6 +415,11 @@
boolean isHeadTrackerEnabled(in AudioDeviceAttributes device);
+ boolean isHeadTrackerAvailable();
+
+ void registerSpatializerHeadTrackerAvailableCallback(
+ in ISpatializerHeadTrackerAvailableCallback cb, boolean register);
+
void setSpatializerEnabled(boolean enabled);
boolean canBeSpatialized(in AudioAttributes aa, in AudioFormat af);
diff --git a/media/java/android/media/tv/interactive/TvInteractiveAppInfo.aidl b/media/java/android/media/ISpatializerHeadTrackerAvailableCallback.aidl
similarity index 62%
copy from media/java/android/media/tv/interactive/TvInteractiveAppInfo.aidl
copy to media/java/android/media/ISpatializerHeadTrackerAvailableCallback.aidl
index 5e15016..dc5ee1d 100644
--- a/media/java/android/media/tv/interactive/TvInteractiveAppInfo.aidl
+++ b/media/java/android/media/ISpatializerHeadTrackerAvailableCallback.aidl
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2021 The Android Open Source Project
+ * Copyright (C) 2022 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -14,6 +14,14 @@
* limitations under the License.
*/
-package android.media.tv.interactive;
+package android.media;
-parcelable TvInteractiveAppInfo;
\ No newline at end of file
+/**
+ * AIDL for the AudioService to signal whether audio device used by Spatializer has head tracker.
+ *
+ * {@hide}
+ */
+oneway interface ISpatializerHeadTrackerAvailableCallback {
+
+ void dispatchSpatializerHeadTrackerAvailable(boolean available);
+}
diff --git a/media/java/android/media/MediaActionSound.java b/media/java/android/media/MediaActionSound.java
index ec56d61..ad1405a 100644
--- a/media/java/android/media/MediaActionSound.java
+++ b/media/java/android/media/MediaActionSound.java
@@ -25,7 +25,8 @@
/**
* <p>A class for producing sounds that match those produced by various actions
- * taken by the media and camera APIs. </p>
+ * taken by the media and camera APIs. It is recommended to call methods in this class
+ * in a background thread since it relies on binder calls.</p>
*
* <p>This class is recommended for use with the {@link android.hardware.camera2} API, since the
* camera2 API does not play any sounds on its own for any capture or video recording actions.</p>
@@ -109,7 +110,7 @@
/**
* <p>Returns true if the application must play the shutter sound in accordance
- * to certain regional restrictions. </p>
+ * to certain regional restrictions.</p>
*
* <p>If this method returns true, applications are strongly recommended to use
* MediaActionSound.play(SHUTTER_CLICK) or START_VIDEO_RECORDING whenever it captures
diff --git a/media/java/android/media/MediaCodec.java b/media/java/android/media/MediaCodec.java
index 4563259..e39914d 100644
--- a/media/java/android/media/MediaCodec.java
+++ b/media/java/android/media/MediaCodec.java
@@ -223,19 +223,19 @@
</thead>
<tbody>
<tr>
- <td>{@code "crop-left"}</td>
+ <td>{@link MediaFormat#KEY_CROP_LEFT}</td>
<td>Integer</td>
<td>The left-coordinate (x) of the crop rectangle</td>
</tr><tr>
- <td>{@code "crop-top"}</td>
+ <td>{@link MediaFormat#KEY_CROP_TOP}</td>
<td>Integer</td>
<td>The top-coordinate (y) of the crop rectangle</td>
</tr><tr>
- <td>{@code "crop-right"}</td>
+ <td>{@link MediaFormat#KEY_CROP_RIGHT}</td>
<td>Integer</td>
<td>The right-coordinate (x) <strong>MINUS 1</strong> of the crop rectangle</td>
</tr><tr>
- <td>{@code "crop-bottom"}</td>
+ <td>{@link MediaFormat#KEY_CROP_BOTTOM}</td>
<td>Integer</td>
<td>The bottom-coordinate (y) <strong>MINUS 1</strong> of the crop rectangle</td>
</tr><tr>
@@ -251,12 +251,16 @@
<pre class=prettyprint>
MediaFormat format = decoder.getOutputFormat(…);
int width = format.getInteger(MediaFormat.KEY_WIDTH);
- if (format.containsKey("crop-left") && format.containsKey("crop-right")) {
- width = format.getInteger("crop-right") + 1 - format.getInteger("crop-left");
+ if (format.containsKey(MediaFormat.KEY_CROP_LEFT)
+ && format.containsKey(MediaFormat.KEY_CROP_RIGHT)) {
+ width = format.getInteger(MediaFormat.KEY_CROP_RIGHT) + 1
+ - format.getInteger(MediaFormat.KEY_CROP_LEFT);
}
int height = format.getInteger(MediaFormat.KEY_HEIGHT);
- if (format.containsKey("crop-top") && format.containsKey("crop-bottom")) {
- height = format.getInteger("crop-bottom") + 1 - format.getInteger("crop-top");
+ if (format.containsKey(MediaFormat.KEY_CROP_TOP)
+ && format.containsKey(MediaFormat.KEY_CROP_BOTTOM)) {
+ height = format.getInteger(MediaFormat.KEY_CROP_BOTTOM) + 1
+ - format.getInteger(MediaFormat.KEY_CROP_TOP);
}
</pre>
<p class=note>
diff --git a/media/java/android/media/MediaFormat.java b/media/java/android/media/MediaFormat.java
index 4956dbe..9dea5b9 100644
--- a/media/java/android/media/MediaFormat.java
+++ b/media/java/android/media/MediaFormat.java
@@ -359,6 +359,42 @@
public static final String KEY_HEIGHT = "height";
/**
+ * A key describing the bottom-coordinate (y) of the crop rectangle.
+ * This is the bottom-most row included in the crop frame,
+ * where row indices start at 0.
+ * Additional information on the crop rectangle semantics can be found at
+ * {@link android.media.MediaCodec}.
+ */
+ public static final String KEY_CROP_BOTTOM = "crop-bottom";
+
+ /**
+ * A key describing the left-coordinate (x) of the crop rectangle.
+ * This is the left-most column included in the crop frame,
+ * where column indices start at 0.
+ * Additional information on the crop rectangle semantics can be found at
+ * {@link android.media.MediaCodec}.
+ */
+ public static final String KEY_CROP_LEFT = "crop-left";
+
+ /**
+ * A key describing the right-coordinate (x) of the crop rectangle.
+ * This is the right-most column included in the crop frame,
+ * where column indices start at 0.
+ * Additional information on the crop rectangle semantics can be found at
+ * {@link android.media.MediaCodec}.
+ */
+ public static final String KEY_CROP_RIGHT = "crop-right";
+
+ /**
+ * A key describing the top-coordinate (y) of the crop rectangle.
+ * This is the top-most row included in the crop frame,
+ * where row indices start at 0.
+ * Additional information on the crop rectangle semantics can be found at
+ * {@link android.media.MediaCodec}.
+ */
+ public static final String KEY_CROP_TOP = "crop-top";
+
+ /**
* A key describing the maximum expected width of the content in a video
* decoder format, in case there are resolution changes in the video content.
* The associated value is an integer
@@ -793,8 +829,11 @@
* By default, the decoder will output the same number of channels as present in the encoded
* stream, if supported. Set this value to limit the number of output channels, and use
* the downmix information in the stream, if available.
- * <p>Values larger than the number of channels in the content to decode are ignored.
+ * <p>Values larger than the number of channels in the content to decode behave just
+ * like the actual channel count of the content (e.g. passing 99 for the decoding of 5.1 content
+ * will behave like using 6).
* <p>This key is only used during decoding.
+ * @deprecated Use the non-AAC-specific key {@link #KEY_MAX_OUTPUT_CHANNEL_COUNT} instead
*/
public static final String KEY_AAC_MAX_OUTPUT_CHANNEL_COUNT = "aac-max-output-channel_count";
diff --git a/media/java/android/media/MediaRoute2Info.java b/media/java/android/media/MediaRoute2Info.java
index ee0293d..283a41a 100644
--- a/media/java/android/media/MediaRoute2Info.java
+++ b/media/java/android/media/MediaRoute2Info.java
@@ -539,6 +539,7 @@
/**
* Gets the Deduplication ID of the route if available.
* @see RouteDiscoveryPreference#shouldRemoveDuplicates()
+ * @hide
*/
@NonNull
public Set<String> getDeduplicationIds() {
@@ -968,6 +969,7 @@
* <p>
* If it's {@code null}, the route will not be removed.
* @see RouteDiscoveryPreference#shouldRemoveDuplicates()
+ * @hide
*/
@NonNull
public Builder setDeduplicationIds(@NonNull Set<String> id) {
diff --git a/media/java/android/media/RouteDiscoveryPreference.java b/media/java/android/media/RouteDiscoveryPreference.java
index 0ba36fe..207460a 100644
--- a/media/java/android/media/RouteDiscoveryPreference.java
+++ b/media/java/android/media/RouteDiscoveryPreference.java
@@ -119,6 +119,7 @@
* first in the provided list will remain.
*
* @see #shouldRemoveDuplicates()
+ * @hide
*/
@NonNull
public List<String> getDeduplicationPackageOrder() {
@@ -130,6 +131,7 @@
* <p>
* If it's not empty, it will only discover routes from the provider whose package name
* belongs to the list.
+ * @hide
*/
@NonNull
public List<String> getAllowedPackages() {
@@ -151,6 +153,7 @@
* Gets whether duplicate routes removal is enabled.
*
* @see #getDeduplicationPackageOrder()
+ * @hide
*/
public boolean shouldRemoveDuplicates() {
return !mPackageOrder.isEmpty();
@@ -293,6 +296,7 @@
* <p>
* If it's non-empty, media router only discovers route from the provider in the list.
* The default value is empty, which discovers routes from all providers.
+ * @hide
*/
@NonNull
public Builder setAllowedPackages(@NonNull List<String> allowedPackages) {
@@ -324,6 +328,7 @@
*
* @param packageOrder ordered list of package names used to remove duplicate routes, or an
* empty list if deduplication should not be enabled.
+ * @hide
*/
@NonNull
public Builder setDeduplicationPackageOrder(@NonNull List<String> packageOrder) {
diff --git a/media/java/android/media/Spatializer.java b/media/java/android/media/Spatializer.java
index be0ef37..74ca4b8 100644
--- a/media/java/android/media/Spatializer.java
+++ b/media/java/android/media/Spatializer.java
@@ -185,6 +185,45 @@
return false;
}
+ /**
+ * Returns whether a head tracker is currently available for the audio device used by the
+ * spatializer effect.
+ * @return true if a head tracker is available and the effect is enabled, false otherwise.
+ * @see OnHeadTrackerAvailableListener
+ * @see #addOnHeadTrackerAvailableListener(Executor, OnHeadTrackerAvailableListener)
+ */
+ public boolean isHeadTrackerAvailable() {
+ try {
+ return mAm.getService().isHeadTrackerAvailable();
+ } catch (RemoteException e) {
+ e.rethrowFromSystemServer();
+ }
+ return false;
+ }
+
+ /**
+ * Adds a listener to be notified of changes to the availability of a head tracker.
+ * @param executor the {@code Executor} handling the callback
+ * @param listener the listener to receive availability updates
+ * @see #removeOnHeadTrackerAvailableListener(OnHeadTrackerAvailableListener)
+ */
+ public void addOnHeadTrackerAvailableListener(@NonNull @CallbackExecutor Executor executor,
+ @NonNull OnHeadTrackerAvailableListener listener) {
+ mHeadTrackerListenerMgr.addListener(executor, listener,
+ "addOnHeadTrackerAvailableListener",
+ () -> new SpatializerHeadTrackerAvailableDispatcherStub());
+ }
+
+ /**
+ * Removes a previously registered listener for the availability of a head tracker.
+ * @param listener the listener previously registered with
+ * {@link #addOnHeadTrackerAvailableListener(Executor, OnHeadTrackerAvailableListener)}
+ */
+ public void removeOnHeadTrackerAvailableListener(
+ @NonNull OnHeadTrackerAvailableListener listener) {
+ mHeadTrackerListenerMgr.removeListener(listener, "removeOnHeadTrackerAvailableListener");
+ }
+
/** @hide */
@IntDef(flag = false, value = {
SPATIALIZER_IMMERSIVE_LEVEL_OTHER,
@@ -401,6 +440,22 @@
@HeadTrackingModeSet int mode);
}
+ /**
+ * Interface to be notified of changes to the availability of a head tracker on the audio
+ * device to be used by the spatializer effect.
+ */
+ public interface OnHeadTrackerAvailableListener {
+ /**
+ * Called when the availability of the head tracker changed.
+ * @param spatializer the {@code Spatializer} instance for which the head tracker
+ * availability was updated
+ * @param available true if the audio device that would output audio processed by
+ * the {@code Spatializer} has a head tracker associated with it, false
+ * otherwise.
+ */
+ void onHeadTrackerAvailableChanged(@NonNull Spatializer spatializer,
+ boolean available);
+ }
/**
* @hide
@@ -827,8 +882,12 @@
/**
* @hide
- * Returns the id of the output stream used for the spatializer effect playback
+ * Returns the id of the output stream used for the spatializer effect playback.
+ * This getter or associated listener {@link OnSpatializerOutputChangedListener} can be used for
+ * handling spatializer output-specific configurations (e.g. disabling speaker post-processing
+ * to avoid double-processing of the spatialized path).
* @return id of the output stream, or 0 if no spatializer playback is active
+ * @see #setOnSpatializerOutputChangedListener(Executor, OnSpatializerOutputChangedListener)
*/
@SystemApi(client = SystemApi.Client.PRIVILEGED_APPS)
@RequiresPermission(android.Manifest.permission.MODIFY_DEFAULT_AUDIO_EFFECTS)
@@ -865,6 +924,8 @@
mOutputDispatcher = new SpatializerOutputDispatcherStub();
try {
mAm.getService().registerSpatializerOutputCallback(mOutputDispatcher);
+ // immediately report the current output
+ mOutputDispatcher.dispatchSpatializerOutputChanged(getOutput());
} catch (RemoteException e) {
mOutputListener = null;
mOutputDispatcher = null;
@@ -935,6 +996,36 @@
}
//-----------------------------------------------------------------------------
+ // head tracker availability callback management and stub
+ /**
+ * manages the OnHeadTrackerAvailableListener listeners and the
+ * SpatializerHeadTrackerAvailableDispatcherStub
+ */
+ private final CallbackUtil.LazyListenerManager<OnHeadTrackerAvailableListener>
+ mHeadTrackerListenerMgr = new CallbackUtil.LazyListenerManager();
+
+ private final class SpatializerHeadTrackerAvailableDispatcherStub
+ extends ISpatializerHeadTrackerAvailableCallback.Stub
+ implements CallbackUtil.DispatcherStub {
+ @Override
+ public void register(boolean register) {
+ try {
+ mAm.getService().registerSpatializerHeadTrackerAvailableCallback(this, register);
+ } catch (RemoteException e) {
+ e.rethrowFromSystemServer();
+ }
+ }
+
+ @Override
+ @SuppressLint("GuardedBy") // lock applied inside callListeners method
+ public void dispatchSpatializerHeadTrackerAvailable(boolean available) {
+ mHeadTrackerListenerMgr.callListeners(
+ (listener) -> listener.onHeadTrackerAvailableChanged(
+ Spatializer.this, available));
+ }
+ }
+
+ //-----------------------------------------------------------------------------
// head pose callback management and stub
private final Object mPoseListenerLock = new Object();
/**
diff --git a/media/java/android/media/projection/IMediaProjection.aidl b/media/java/android/media/projection/IMediaProjection.aidl
index 19fc052..b136d5b 100644
--- a/media/java/android/media/projection/IMediaProjection.aidl
+++ b/media/java/android/media/projection/IMediaProjection.aidl
@@ -17,6 +17,7 @@
package android.media.projection;
import android.media.projection.IMediaProjectionCallback;
+import android.window.WindowContainerToken;
/** {@hide} */
interface IMediaProjection {
@@ -28,4 +29,16 @@
int applyVirtualDisplayFlags(int flags);
void registerCallback(IMediaProjectionCallback callback);
void unregisterCallback(IMediaProjectionCallback callback);
+
+ /**
+ * Returns the {@link android.window.WindowContainerToken} identifying the task to record, or
+ * {@code null} if there is none.
+ */
+ WindowContainerToken getTaskRecordingWindowContainerToken();
+
+ /**
+ * Updates the {@link android.window.WindowContainerToken} identifying the task to record, or
+ * {@code null} if there is none.
+ */
+ void setTaskRecordingWindowContainerToken(in WindowContainerToken token);
}
diff --git a/media/java/android/media/projection/MediaProjection.java b/media/java/android/media/projection/MediaProjection.java
index 4dde5e8..b5f9593 100644
--- a/media/java/android/media/projection/MediaProjection.java
+++ b/media/java/android/media/projection/MediaProjection.java
@@ -25,13 +25,14 @@
import android.hardware.display.VirtualDisplay;
import android.hardware.display.VirtualDisplayConfig;
import android.os.Handler;
-import android.os.IBinder;
import android.os.RemoteException;
import android.util.ArrayMap;
import android.util.Log;
import android.view.ContentRecordingSession;
+import android.view.IWindowManager;
import android.view.Surface;
import android.view.WindowManagerGlobal;
+import android.window.WindowContainerToken;
import java.util.Map;
@@ -171,16 +172,34 @@
@NonNull VirtualDisplayConfig.Builder virtualDisplayConfig,
@Nullable VirtualDisplay.Callback callback, @Nullable Handler handler) {
try {
- final Context windowContext = mContext.createWindowContext(
- mContext.getDisplayNoVerify(),
- TYPE_APPLICATION, null /* options */);
- final IBinder windowContextToken = windowContext.getWindowContextToken();
+ final IWindowManager wmService = WindowManagerGlobal.getWindowManagerService();
+ final WindowContainerToken taskWindowContainerToken =
+ mImpl.getTaskRecordingWindowContainerToken();
+ Context windowContext = null;
+ ContentRecordingSession session;
+ if (taskWindowContainerToken == null) {
+ windowContext = mContext.createWindowContext(mContext.getDisplayNoVerify(),
+ TYPE_APPLICATION, null /* options */);
+ session = ContentRecordingSession.createDisplaySession(
+ windowContext.getWindowContextToken());
+ } else {
+ session = ContentRecordingSession.createTaskSession(
+ taskWindowContainerToken.asBinder());
+ }
virtualDisplayConfig.setWindowManagerMirroring(true);
final DisplayManager dm = mContext.getSystemService(DisplayManager.class);
final VirtualDisplay virtualDisplay = dm.createVirtualDisplay(this,
- virtualDisplayConfig.build(),
- callback, handler, windowContext);
- setSession(windowContextToken, virtualDisplay);
+ virtualDisplayConfig.build(), callback, handler, windowContext);
+ if (virtualDisplay == null) {
+ // Since WM handling a new display and DM creating a new VirtualDisplay is async,
+ // WM may have tried to start task recording and encountered an error that required
+ // stopping recording entirely. The VirtualDisplay would then be null when the
+ // MediaProjection is no longer active.
+ return null;
+ }
+ session.setDisplayId(virtualDisplay.getDisplay().getDisplayId());
+ // Successfully set up, so save the current session details.
+ wmService.setContentRecordingSession(session);
return virtualDisplay;
} catch (RemoteException e) {
// Can not capture if WMS is not accessible, so bail out.
@@ -189,28 +208,6 @@
}
/**
- * Updates the {@link ContentRecordingSession} describing the recording taking place on this
- * {@link VirtualDisplay}.
- *
- * @throws RemoteException if updating the session on the server failed.
- */
- private void setSession(@NonNull IBinder windowContextToken,
- @Nullable VirtualDisplay virtualDisplay)
- throws RemoteException {
- if (virtualDisplay == null) {
- // Not able to set up a new VirtualDisplay.
- return;
- }
- // Identify the VirtualDisplay that will be hosting the recording.
- ContentRecordingSession session = ContentRecordingSession.createDisplaySession(
- windowContextToken);
- session.setDisplayId(virtualDisplay.getDisplay().getDisplayId());
- // TODO(b/216625226) handle task recording.
- // Successfully set up, so save the current session details.
- WindowManagerGlobal.getWindowManagerService().setContentRecordingSession(session);
- }
-
- /**
* Stops projection.
*/
public void stop() {
diff --git a/media/java/android/media/tv/AdRequest.java b/media/java/android/media/tv/AdRequest.java
index 0542c55..f2fb93d 100644
--- a/media/java/android/media/tv/AdRequest.java
+++ b/media/java/android/media/tv/AdRequest.java
@@ -163,7 +163,11 @@
/**
* Gets the metadata of the media file.
- * <p>This includes additional information the TV input needs to play the AD media.
+ *
+ * <p>This includes additional information the TV input needs to play the AD media. This may
+ * include fields in {@link android.media.MediaFormat} like
+ * {@link android.media.MediaFormat#KEY_SAMPLE_RATE}, or integrity information like SHA. What
+ * data is included depends on the format of the media file.
*
* @return The metadata of the media file. Can be an empty bundle for
* {@link #REQUEST_TYPE_STOP}.
diff --git a/media/java/android/media/tv/AitInfo.java b/media/java/android/media/tv/AitInfo.java
index 8e80a62..c88a2b5 100644
--- a/media/java/android/media/tv/AitInfo.java
+++ b/media/java/android/media/tv/AitInfo.java
@@ -17,7 +17,7 @@
package android.media.tv;
import android.annotation.NonNull;
-import android.media.tv.interactive.TvInteractiveAppInfo;
+import android.media.tv.interactive.TvInteractiveAppServiceInfo;
import android.os.Parcel;
import android.os.Parcelable;
@@ -50,7 +50,7 @@
/**
* Constructs AIT info.
*/
- public AitInfo(@TvInteractiveAppInfo.InteractiveAppType int type, int version) {
+ public AitInfo(@TvInteractiveAppServiceInfo.InteractiveAppType int type, int version) {
mType = type;
mVersion = version;
}
@@ -58,7 +58,7 @@
/**
* Gets interactive app type.
*/
- @TvInteractiveAppInfo.InteractiveAppType
+ @TvInteractiveAppServiceInfo.InteractiveAppType
public int getType() {
return mType;
}
diff --git a/media/java/android/media/tv/CommandRequest.java b/media/java/android/media/tv/CommandRequest.java
index ffb6e07..3245fb5 100644
--- a/media/java/android/media/tv/CommandRequest.java
+++ b/media/java/android/media/tv/CommandRequest.java
@@ -24,6 +24,8 @@
* A request for command from broadcast signal.
*/
public final class CommandRequest extends BroadcastInfoRequest implements Parcelable {
+ public static final String ARGUMENT_TYPE_XML = "xml";
+ public static final String ARGUMENT_TYPE_JSON = "json";
private static final @TvInputManager.BroadcastInfoType int REQUEST_TYPE =
TvInputManager.BROADCAST_INFO_TYPE_COMMAND;
@@ -41,35 +43,38 @@
}
};
- private final String mNameSpace;
+ private final String mNamespace;
private final String mName;
private final String mArguments;
+ private final String mArgumentType;
static CommandRequest createFromParcelBody(Parcel in) {
return new CommandRequest(in);
}
- public CommandRequest(int requestId, @RequestOption int option, @NonNull String nameSpace,
- @NonNull String name, @NonNull String arguments) {
+ public CommandRequest(int requestId, @RequestOption int option, @NonNull String namespace,
+ @NonNull String name, @NonNull String arguments, @NonNull String argumentType) {
super(REQUEST_TYPE, requestId, option);
- mNameSpace = nameSpace;
+ mNamespace = namespace;
mName = name;
mArguments = arguments;
+ mArgumentType = argumentType;
}
CommandRequest(Parcel source) {
super(REQUEST_TYPE, source);
- mNameSpace = source.readString();
+ mNamespace = source.readString();
mName = source.readString();
mArguments = source.readString();
+ mArgumentType = source.readString();
}
/**
* Gets the namespace of the command.
*/
@NonNull
- public String getNameSpace() {
- return mNameSpace;
+ public String getNamespace() {
+ return mNamespace;
}
/**
@@ -89,6 +94,15 @@
return mArguments;
}
+ /**
+ * Gets the argument type of the command.
+ * It could be either JSON or XML.
+ */
+ @NonNull
+ public String getArgumentType() {
+ return mArgumentType;
+ }
+
@Override
public int describeContents() {
return 0;
@@ -97,8 +111,9 @@
@Override
public void writeToParcel(@NonNull Parcel dest, int flags) {
super.writeToParcel(dest, flags);
- dest.writeString(mNameSpace);
+ dest.writeString(mNamespace);
dest.writeString(mName);
dest.writeString(mArguments);
+ dest.writeString(mArgumentType);
}
}
diff --git a/media/java/android/media/tv/CommandResponse.java b/media/java/android/media/tv/CommandResponse.java
index c8853f1..8e448cd 100644
--- a/media/java/android/media/tv/CommandResponse.java
+++ b/media/java/android/media/tv/CommandResponse.java
@@ -25,6 +25,8 @@
* A response for command from broadcast signal.
*/
public final class CommandResponse extends BroadcastInfoResponse implements Parcelable {
+ public static final String RESPONSE_TYPE_XML = "xml";
+ public static final String RESPONSE_TYPE_JSON = "json";
private static final @TvInputManager.BroadcastInfoType int RESPONSE_TYPE =
TvInputManager.BROADCAST_INFO_TYPE_COMMAND;
@@ -43,20 +45,23 @@
};
private final String mResponse;
+ private final String mResponseType;
static CommandResponse createFromParcelBody(Parcel in) {
return new CommandResponse(in);
}
- public CommandResponse(int requestId, int sequence,
- @ResponseResult int responseResult, @Nullable String response) {
+ public CommandResponse(int requestId, int sequence, @ResponseResult int responseResult,
+ @Nullable String response, @NonNull String responseType) {
super(RESPONSE_TYPE, requestId, sequence, responseResult);
mResponse = response;
+ mResponseType = responseType;
}
CommandResponse(Parcel source) {
super(RESPONSE_TYPE, source);
mResponse = source.readString();
+ mResponseType = source.readString();
}
/**
@@ -68,6 +73,15 @@
return mResponse;
}
+ /**
+ * Gets the type of the command response.
+ * It could be either JSON or XML.
+ */
+ @NonNull
+ public String getResponseType() {
+ return mResponseType;
+ }
+
@Override
public int describeContents() {
return 0;
@@ -77,5 +91,6 @@
public void writeToParcel(@NonNull Parcel dest, int flags) {
super.writeToParcel(dest, flags);
dest.writeString(mResponse);
+ dest.writeString(mResponseType);
}
}
diff --git a/media/java/android/media/tv/SectionRequest.java b/media/java/android/media/tv/SectionRequest.java
index 5957528..078e832 100644
--- a/media/java/android/media/tv/SectionRequest.java
+++ b/media/java/android/media/tv/SectionRequest.java
@@ -80,6 +80,11 @@
/**
* Gets the version number of requested session. If it is null, value will be -1.
+ * <p>The consistency of version numbers between request and response depends on
+ * {@link BroadcastInfoRequest.RequestOption}. If the request has RequestOption value
+ * REQUEST_OPTION_AUTO_UPDATE, then the response may be set to the latest version which may be
+ * different from the version of the request. Otherwise, response with a different version from
+ * its request will be considered invalid.
*/
public int getVersion() {
return mVersion;
diff --git a/media/java/android/media/tv/SectionResponse.java b/media/java/android/media/tv/SectionResponse.java
index 35836be..f38ea9d 100644
--- a/media/java/android/media/tv/SectionResponse.java
+++ b/media/java/android/media/tv/SectionResponse.java
@@ -74,14 +74,20 @@
}
/**
- * Gets the Version number of requested session.
+ * Gets the Version number of requested session. If it is null, value will be -1.
+ * <p>The consistency of version numbers between request and response depends on
+ * {@link BroadcastInfoRequest.RequestOption}. If the request has RequestOption value
+ * REQUEST_OPTION_AUTO_UPDATE, then the response may be set to the latest version which may be
+ * different from the version of the request. Otherwise, response with a different version from
+ * its request will be considered invalid.
*/
public int getVersion() {
return mVersion;
}
/**
- * Gets the raw data of session.
+ * Gets the raw data of session. The sessionData field represents payload data of the session
+ * after session header, which includes version and sessionId.
*/
@NonNull
public Bundle getSessionData() {
diff --git a/media/java/android/media/tv/StreamEventResponse.java b/media/java/android/media/tv/StreamEventResponse.java
index f952ce9..28dff37 100644
--- a/media/java/android/media/tv/StreamEventResponse.java
+++ b/media/java/android/media/tv/StreamEventResponse.java
@@ -43,7 +43,7 @@
};
private final int mEventId;
- private final long mNpt;
+ private final long mNptMillis;
private final byte[] mData;
static StreamEventResponse createFromParcelBody(Parcel in) {
@@ -51,17 +51,17 @@
}
public StreamEventResponse(int requestId, int sequence, @ResponseResult int responseResult,
- int eventId, long npt, @Nullable byte[] data) {
+ int eventId, long nptMillis, @Nullable byte[] data) {
super(RESPONSE_TYPE, requestId, sequence, responseResult);
mEventId = eventId;
- mNpt = npt;
+ mNptMillis = nptMillis;
mData = data;
}
private StreamEventResponse(@NonNull Parcel source) {
super(RESPONSE_TYPE, source);
mEventId = source.readInt();
- mNpt = source.readLong();
+ mNptMillis = source.readLong();
int dataLength = source.readInt();
mData = new byte[dataLength];
source.readByteArray(mData);
@@ -76,9 +76,10 @@
/**
* Returns the NPT(Normal Play Time) value when the event occurred or will occur.
+ * <p>The time unit of NPT is millisecond.
*/
- public long getNpt() {
- return mNpt;
+ public long getNptMillis() {
+ return mNptMillis;
}
/**
@@ -98,7 +99,7 @@
public void writeToParcel(@NonNull Parcel dest, int flags) {
super.writeToParcel(dest, flags);
dest.writeInt(mEventId);
- dest.writeLong(mNpt);
+ dest.writeLong(mNptMillis);
dest.writeInt(mData.length);
dest.writeByteArray(mData);
}
diff --git a/media/java/android/media/tv/TableRequest.java b/media/java/android/media/tv/TableRequest.java
index 37df4ea..a1a6b51 100644
--- a/media/java/android/media/tv/TableRequest.java
+++ b/media/java/android/media/tv/TableRequest.java
@@ -91,7 +91,12 @@
}
/**
- * Gets the version number of requested table.
+ * Gets the version number of requested table. If it is null, value will be -1.
+ * <p>The consistency of version numbers between request and response depends on
+ * {@link BroadcastInfoRequest.RequestOption}. If the request has RequestOption value
+ * REQUEST_OPTION_AUTO_UPDATE, then the response may be set to the latest version which may be
+ * different from the version of the request. Otherwise, response with a different version from
+ * its request will be considered invalid.
*/
public int getVersion() {
return mVersion;
diff --git a/media/java/android/media/tv/TableResponse.java b/media/java/android/media/tv/TableResponse.java
index e9f1136..afc9bee 100644
--- a/media/java/android/media/tv/TableResponse.java
+++ b/media/java/android/media/tv/TableResponse.java
@@ -76,7 +76,12 @@
}
/**
- * Gets the Version number of table.
+ * Gets the version number of requested table. If it is null, value will be -1.
+ * <p>The consistency of version numbers between request and response depends on
+ * {@link BroadcastInfoRequest.RequestOption}. If the request has RequestOption value
+ * REQUEST_OPTION_AUTO_UPDATE, then the response may be set to the latest version which may be
+ * different from the version of the request. Otherwise, response with a different version from
+ * its request will be considered invalid.
*/
public int getVersion() {
return mVersion;
diff --git a/media/java/android/media/tv/TimelineResponse.java b/media/java/android/media/tv/TimelineResponse.java
index fbeb0c4..7de30f5 100644
--- a/media/java/android/media/tv/TimelineResponse.java
+++ b/media/java/android/media/tv/TimelineResponse.java
@@ -18,6 +18,7 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
+import android.net.Uri;
import android.os.Parcel;
import android.os.Parcelable;
@@ -79,8 +80,8 @@
* that conveys Time Values on it.
*/
@Nullable
- public String getSelector() {
- return mSelector;
+ public Uri getSelector() {
+ return Uri.parse(mSelector);
}
/**
diff --git a/media/java/android/media/tv/TvInputManager.java b/media/java/android/media/tv/TvInputManager.java
index 69fe5ee..149c2f4 100644
--- a/media/java/android/media/tv/TvInputManager.java
+++ b/media/java/android/media/tv/TvInputManager.java
@@ -680,7 +680,7 @@
* @param session A {@link TvInputManager.Session} associated with this callback.
* @param strength The current signal strength.
*/
- public void onSignalStrength(Session session, @SignalStrength int strength) {
+ public void onSignalStrengthUpdated(Session session, @SignalStrength int strength) {
}
/**
@@ -898,7 +898,7 @@
mHandler.post(new Runnable() {
@Override
public void run() {
- mSessionCallback.onSignalStrength(mSession, strength);
+ mSessionCallback.onSignalStrengthUpdated(mSession, strength);
if (mSession.mIAppNotificationEnabled
&& mSession.getInteractiveAppSession() != null) {
mSession.getInteractiveAppSession().notifySignalStrength(strength);
diff --git a/media/java/android/media/tv/TvView.java b/media/java/android/media/tv/TvView.java
index 4d63af7..ff3d06c 100644
--- a/media/java/android/media/tv/TvView.java
+++ b/media/java/android/media/tv/TvView.java
@@ -1083,7 +1083,7 @@
* @param inputId The ID of the TV input bound to this view.
* @param strength The current signal strength.
*/
- public void onSignalStrength(
+ public void onSignalStrengthUpdated(
@NonNull String inputId, @TvInputManager.SignalStrength int strength) {
}
@@ -1406,16 +1406,16 @@
}
@Override
- public void onSignalStrength(Session session, int strength) {
+ public void onSignalStrengthUpdated(Session session, int strength) {
if (DEBUG) {
- Log.d(TAG, "onSignalStrength(strength=" + strength + ")");
+ Log.d(TAG, "onSignalStrengthUpdated(strength=" + strength + ")");
}
if (this != mSessionCallback) {
- Log.w(TAG, "onSignalStrength - session not created");
+ Log.w(TAG, "onSignalStrengthUpdated - session not created");
return;
}
if (mCallback != null) {
- mCallback.onSignalStrength(mInputId, strength);
+ mCallback.onSignalStrengthUpdated(mInputId, strength);
}
}
diff --git a/media/java/android/media/tv/interactive/AppLinkInfo.aidl b/media/java/android/media/tv/interactive/AppLinkInfo.aidl
index 6759fc4..f551c9f 100644
--- a/media/java/android/media/tv/interactive/AppLinkInfo.aidl
+++ b/media/java/android/media/tv/interactive/AppLinkInfo.aidl
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2021 The Android Open Source Project
+ * Copyright 2021 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/media/java/android/media/tv/interactive/AppLinkInfo.java b/media/java/android/media/tv/interactive/AppLinkInfo.java
index 0eb6fa8..d5e995c 100644
--- a/media/java/android/media/tv/interactive/AppLinkInfo.java
+++ b/media/java/android/media/tv/interactive/AppLinkInfo.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2021 The Android Open Source Project
+ * Copyright 2021 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -17,8 +17,8 @@
package android.media.tv.interactive;
import android.annotation.NonNull;
-import android.annotation.Nullable;
import android.content.ComponentName;
+import android.net.Uri;
import android.os.Parcel;
import android.os.Parcelable;
@@ -27,68 +27,41 @@
*/
public final class AppLinkInfo implements Parcelable {
private @NonNull ComponentName mComponentName;
- private @Nullable String mUriScheme;
- private @Nullable String mUriHost;
- private @Nullable String mUriPrefix;
-
+ private @NonNull Uri mUri;
/**
* Creates a new AppLinkInfo.
+ *
+ * @param packageName Package Name of AppLinkInfo.
+ * @param className Class Name of AppLinkInfo.
+ * @param uriString Uri of AppLinkInfo.
*/
- private AppLinkInfo(
+ public AppLinkInfo(
@NonNull String packageName,
@NonNull String className,
- @Nullable String uriScheme,
- @Nullable String uriHost,
- @Nullable String uriPrefix) {
+ @NonNull String uriString) {
com.android.internal.util.AnnotationValidations.validate(
NonNull.class, null, packageName);
com.android.internal.util.AnnotationValidations.validate(
NonNull.class, null, className);
this.mComponentName = new ComponentName(packageName, className);
- this.mUriScheme = uriScheme;
- this.mUriHost = uriHost;
- this.mUriPrefix = uriPrefix;
+ this.mUri = Uri.parse(uriString);
}
/**
- * Gets package name of the App link.
+ * Gets component name of the App link, which contains package name and class name.
*/
@NonNull
- public String getPackageName() {
- return mComponentName.getPackageName();
+ public ComponentName getComponentName() {
+ return mComponentName;
}
/**
- * Gets package class of the App link.
+ * Gets URI of the App link.
*/
@NonNull
- public String getClassName() {
- return mComponentName.getClassName();
- }
-
- /**
- * Gets URI scheme of the App link.
- */
- @Nullable
- public String getUriScheme() {
- return mUriScheme;
- }
-
- /**
- * Gets URI host of the App link.
- */
- @Nullable
- public String getUriHost() {
- return mUriHost;
- }
-
- /**
- * Gets URI prefix of the App link.
- */
- @Nullable
- public String getUriPrefix() {
- return mUriPrefix;
+ public Uri getUri() {
+ return mUri;
}
@Override
@@ -96,19 +69,15 @@
return "AppLinkInfo { "
+ "packageName = " + mComponentName.getPackageName() + ", "
+ "className = " + mComponentName.getClassName() + ", "
- + "uriScheme = " + mUriScheme + ", "
- + "uriHost = " + mUriHost + ", "
- + "uriPrefix = " + mUriPrefix
+ + "uri = " + mUri.toString()
+ " }";
}
@Override
public void writeToParcel(@NonNull Parcel dest, int flags) {
- dest.writeString(mComponentName.getPackageName());
- dest.writeString(mComponentName.getClassName());
- dest.writeString(mUriScheme);
- dest.writeString(mUriHost);
- dest.writeString(mUriPrefix);
+ mComponentName.writeToParcel(dest, flags);
+ String uriString = mUri == null ? null : mUri.toString();
+ dest.writeString(uriString);
}
@Override
@@ -117,20 +86,13 @@
}
/* package-private */ AppLinkInfo(@NonNull Parcel in) {
- String packageName = in.readString();
- String className = in.readString();
- String uriScheme = in.readString();
- String uriHost = in.readString();
- String uriPrefix = in.readString();
-
+ mComponentName = ComponentName.readFromParcel(in);
com.android.internal.util.AnnotationValidations.validate(
- NonNull.class, null, packageName);
+ NonNull.class, null, mComponentName.getPackageName());
com.android.internal.util.AnnotationValidations.validate(
- NonNull.class, null, className);
- this.mComponentName = new ComponentName(packageName, className);
- this.mUriScheme = uriScheme;
- this.mUriHost = uriHost;
- this.mUriPrefix = uriPrefix;
+ NonNull.class, null, mComponentName.getClassName());
+ String uriString = in.readString();
+ mUri = uriString == null ? null : Uri.parse(uriString);
}
@NonNull
@@ -146,68 +108,4 @@
return new AppLinkInfo(in);
}
};
-
- /**
- * A builder for {@link AppLinkInfo}
- */
- public static final class Builder {
- private @NonNull String mPackageName;
- private @NonNull String mClassName;
- private @Nullable String mUriScheme;
- private @Nullable String mUriHost;
- private @Nullable String mUriPrefix;
-
- /**
- * Creates a new Builder.
- */
- public Builder(
- @NonNull String packageName,
- @NonNull String className) {
- mPackageName = packageName;
- com.android.internal.util.AnnotationValidations.validate(
- NonNull.class, null, mPackageName);
- mClassName = className;
- com.android.internal.util.AnnotationValidations.validate(
- NonNull.class, null, mClassName);
- }
-
- /**
- * Sets URI scheme of the App link.
- */
- @NonNull
- public Builder setUriScheme(@NonNull String value) {
- mUriScheme = value;
- return this;
- }
-
- /**
- * Sets URI host of the App link.
- */
- @NonNull
- public Builder setUriHost(@NonNull String value) {
- mUriHost = value;
- return this;
- }
-
- /**
- * Sets URI prefix of the App link.
- */
- @NonNull
- public Builder setUriPrefix(@NonNull String value) {
- mUriPrefix = value;
- return this;
- }
-
- /** Builds the instance. This builder should not be touched after calling this! */
- @NonNull
- public AppLinkInfo build() {
- AppLinkInfo o = new AppLinkInfo(
- mPackageName,
- mClassName,
- mUriScheme,
- mUriHost,
- mUriPrefix);
- return o;
- }
- }
}
diff --git a/media/java/android/media/tv/interactive/ITvInteractiveAppClient.aidl b/media/java/android/media/tv/interactive/ITvInteractiveAppClient.aidl
index a3e58d1..50aa6fe 100644
--- a/media/java/android/media/tv/interactive/ITvInteractiveAppClient.aidl
+++ b/media/java/android/media/tv/interactive/ITvInteractiveAppClient.aidl
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2021 The Android Open Source Project
+ * Copyright 2021 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -44,5 +44,7 @@
void onRequestStreamVolume(int seq);
void onRequestTrackInfoList(int seq);
void onRequestCurrentTvInputId(int seq);
+ void onRequestSigning(
+ in String id, in String algorithm, in String alias, in byte[] data, int seq);
void onAdRequest(in AdRequest request, int Seq);
}
diff --git a/media/java/android/media/tv/interactive/ITvInteractiveAppManager.aidl b/media/java/android/media/tv/interactive/ITvInteractiveAppManager.aidl
index aaabe34..9ff564e 100644
--- a/media/java/android/media/tv/interactive/ITvInteractiveAppManager.aidl
+++ b/media/java/android/media/tv/interactive/ITvInteractiveAppManager.aidl
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2021 The Android Open Source Project
+ * Copyright 2021 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -23,7 +23,7 @@
import android.media.tv.interactive.AppLinkInfo;
import android.media.tv.interactive.ITvInteractiveAppClient;
import android.media.tv.interactive.ITvInteractiveAppManagerCallback;
-import android.media.tv.interactive.TvInteractiveAppInfo;
+import android.media.tv.interactive.TvInteractiveAppServiceInfo;
import android.net.Uri;
import android.os.Bundle;
import android.view.Surface;
@@ -33,8 +33,7 @@
* @hide
*/
interface ITvInteractiveAppManager {
- List<TvInteractiveAppInfo> getTvInteractiveAppServiceList(int userId);
- void prepare(String tiasId, int type, int userId);
+ List<TvInteractiveAppServiceInfo> getTvInteractiveAppServiceList(int userId);
void registerAppLinkInfo(String tiasId, in AppLinkInfo info, int userId);
void unregisterAppLinkInfo(String tiasId, in AppLinkInfo info, int userId);
void sendAppLinkCommand(String tiasId, in Bundle command, int userId);
@@ -50,6 +49,8 @@
void sendStreamVolume(in IBinder sessionToken, float volume, int userId);
void sendTrackInfoList(in IBinder sessionToken, in List<TvTrackInfo> tracks, int userId);
void sendCurrentTvInputId(in IBinder sessionToken, in String inputId, int userId);
+ void sendSigningResult(in IBinder sessionToken, in String signingId, in byte[] result,
+ int userId);
void createSession(in ITvInteractiveAppClient client, in String iAppServiceId, int type,
int seq, int userId);
void releaseSession(in IBinder sessionToken, int userId);
diff --git a/media/java/android/media/tv/interactive/ITvInteractiveAppManagerCallback.aidl b/media/java/android/media/tv/interactive/ITvInteractiveAppManagerCallback.aidl
index 23be4c6..fed86dc 100644
--- a/media/java/android/media/tv/interactive/ITvInteractiveAppManagerCallback.aidl
+++ b/media/java/android/media/tv/interactive/ITvInteractiveAppManagerCallback.aidl
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2021 The Android Open Source Project
+ * Copyright 2021 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -16,7 +16,7 @@
package android.media.tv.interactive;
-import android.media.tv.interactive.TvInteractiveAppInfo;
+import android.media.tv.interactive.TvInteractiveAppServiceInfo;
/**
* Interface to receive callbacks from ITvInteractiveAppManager regardless of sessions.
@@ -26,6 +26,6 @@
void onInteractiveAppServiceAdded(in String iAppServiceId);
void onInteractiveAppServiceRemoved(in String iAppServiceId);
void onInteractiveAppServiceUpdated(in String iAppServiceId);
- void onTvInteractiveAppInfoUpdated(in TvInteractiveAppInfo tvIAppInfo);
+ void onTvInteractiveAppServiceInfoUpdated(in TvInteractiveAppServiceInfo tvIAppInfo);
void onStateChanged(in String iAppServiceId, int type, int state, int err);
}
\ No newline at end of file
diff --git a/media/java/android/media/tv/interactive/ITvInteractiveAppService.aidl b/media/java/android/media/tv/interactive/ITvInteractiveAppService.aidl
index b6d518f..fb58ca7 100644
--- a/media/java/android/media/tv/interactive/ITvInteractiveAppService.aidl
+++ b/media/java/android/media/tv/interactive/ITvInteractiveAppService.aidl
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2021 The Android Open Source Project
+ * Copyright 2021 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -32,7 +32,6 @@
void unregisterCallback(in ITvInteractiveAppServiceCallback callback);
void createSession(in InputChannel channel, in ITvInteractiveAppSessionCallback callback,
in String iAppServiceId, int type);
- void prepare(int type);
void registerAppLinkInfo(in AppLinkInfo info);
void unregisterAppLinkInfo(in AppLinkInfo info);
void sendAppLinkCommand(in Bundle command);
diff --git a/media/java/android/media/tv/interactive/ITvInteractiveAppServiceCallback.aidl b/media/java/android/media/tv/interactive/ITvInteractiveAppServiceCallback.aidl
index 970b943..87b3c1d 100644
--- a/media/java/android/media/tv/interactive/ITvInteractiveAppServiceCallback.aidl
+++ b/media/java/android/media/tv/interactive/ITvInteractiveAppServiceCallback.aidl
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2021 The Android Open Source Project
+ * Copyright 2021 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/media/java/android/media/tv/interactive/ITvInteractiveAppSession.aidl b/media/java/android/media/tv/interactive/ITvInteractiveAppSession.aidl
index c449d2475..e14b2bb 100644
--- a/media/java/android/media/tv/interactive/ITvInteractiveAppSession.aidl
+++ b/media/java/android/media/tv/interactive/ITvInteractiveAppSession.aidl
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2021 The Android Open Source Project
+ * Copyright 2021 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -42,6 +42,7 @@
void sendStreamVolume(float volume);
void sendTrackInfoList(in List<TvTrackInfo> tracks);
void sendCurrentTvInputId(in String inputId);
+ void sendSigningResult(in String signingId, in byte[] result);
void release();
void notifyTuned(in Uri channelUri);
void notifyTrackSelected(int type, in String trackId);
diff --git a/media/java/android/media/tv/interactive/ITvInteractiveAppSessionCallback.aidl b/media/java/android/media/tv/interactive/ITvInteractiveAppSessionCallback.aidl
index 385f0d4..32b08b7 100644
--- a/media/java/android/media/tv/interactive/ITvInteractiveAppSessionCallback.aidl
+++ b/media/java/android/media/tv/interactive/ITvInteractiveAppSessionCallback.aidl
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2021 The Android Open Source Project
+ * Copyright 2021 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -43,5 +43,6 @@
void onRequestStreamVolume();
void onRequestTrackInfoList();
void onRequestCurrentTvInputId();
+ void onRequestSigning(in String id, in String algorithm, in String alias, in byte[] data);
void onAdRequest(in AdRequest request);
}
diff --git a/media/java/android/media/tv/interactive/TvInteractiveAppManager.java b/media/java/android/media/tv/interactive/TvInteractiveAppManager.java
index 9eb4a6c..d3cbcdc 100755
--- a/media/java/android/media/tv/interactive/TvInteractiveAppManager.java
+++ b/media/java/android/media/tv/interactive/TvInteractiveAppManager.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2021 The Android Open Source Project
+ * Copyright 2021 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -28,7 +28,6 @@
import android.media.tv.BroadcastInfoRequest;
import android.media.tv.BroadcastInfoResponse;
import android.media.tv.TvContentRating;
-import android.media.tv.TvInputInfo;
import android.media.tv.TvInputManager;
import android.media.tv.TvTrackInfo;
import android.net.Uri;
@@ -249,7 +248,7 @@
*
* @see #sendAppLinkCommand(String, Bundle)
* @see #ACTION_APP_LINK_COMMAND
- * @see android.media.tv.interactive.TvInteractiveAppInfo#getId()
+ * @see TvInteractiveAppServiceInfo#getId()
*/
public static final String INTENT_KEY_INTERACTIVE_APP_SERVICE_ID = "interactive_app_id";
@@ -269,7 +268,7 @@
*
* @see #sendAppLinkCommand(String, Bundle)
* @see #ACTION_APP_LINK_COMMAND
- * @see android.media.tv.interactive.TvInteractiveAppInfo#getSupportedTypes()
+ * @see android.media.tv.interactive.TvInteractiveAppServiceInfo#getSupportedTypes()
* @see android.media.tv.interactive.TvInteractiveAppView#createBiInteractiveApp(Uri, Bundle)
*/
public static final String INTENT_KEY_BI_INTERACTIVE_APP_TYPE = "bi_interactive_app_type";
@@ -285,6 +284,16 @@
*/
public static final String INTENT_KEY_BI_INTERACTIVE_APP_URI = "bi_interactive_app_uri";
+ /**
+ * Intent key for command type. It's used to send app command to TV app. The value of this key
+ * could vary according to TV apps.
+ * <p>Type: String
+ *
+ * @see #sendAppLinkCommand(String, Bundle)
+ * @see #ACTION_APP_LINK_COMMAND
+ */
+ public static final String INTENT_KEY_COMMAND_TYPE = "command_type";
+
private final ITvInteractiveAppManager mService;
private final int mUserId;
@@ -478,6 +487,19 @@
}
@Override
+ public void onRequestSigning(
+ String id, String algorithm, String alias, byte[] data, int seq) {
+ synchronized (mSessionCallbackRecordMap) {
+ SessionCallbackRecord record = mSessionCallbackRecordMap.get(seq);
+ if (record == null) {
+ Log.e(TAG, "Callback not found for seq " + seq);
+ return;
+ }
+ record.postRequestSigning(id, algorithm, alias, data);
+ }
+ }
+
+ @Override
public void onSessionStateChanged(int state, int err, int seq) {
synchronized (mSessionCallbackRecordMap) {
SessionCallbackRecord record = mSessionCallbackRecordMap.get(seq);
@@ -543,11 +565,11 @@
}
@Override
- public void onTvInteractiveAppInfoUpdated(TvInteractiveAppInfo iAppInfo) {
+ public void onTvInteractiveAppServiceInfoUpdated(TvInteractiveAppServiceInfo iAppInfo) {
// TODO: add public API updateInteractiveAppInfo()
synchronized (mLock) {
for (TvInteractiveAppCallbackRecord record : mCallbackRecords) {
- record.postTvInteractiveAppInfoUpdated(iAppInfo);
+ record.postTvInteractiveAppServiceInfoUpdated(iAppInfo);
}
}
}
@@ -611,16 +633,17 @@
* This is called when the information about an existing TV Interactive App service has been
* updated.
*
- * <p>Because the system automatically creates a <code>TvInteractiveAppInfo</code> object
- * for each TV Interactive App service based on the information collected from the
+ * <p>Because the system automatically creates a <code>TvInteractiveAppServiceInfo</code>
+ * object for each TV Interactive App service based on the information collected from the
* <code>AndroidManifest.xml</code>, this method is only called back when such information
* has changed dynamically.
*
- * @param iAppInfo The <code>TvInteractiveAppInfo</code> object that contains new
+ * @param iAppInfo The <code>TvInteractiveAppServiceInfo</code> object that contains new
* information.
* @hide
*/
- public void onTvInteractiveAppInfoUpdated(@NonNull TvInteractiveAppInfo iAppInfo) {
+ public void onTvInteractiveAppServiceInfoUpdated(
+ @NonNull TvInteractiveAppServiceInfo iAppInfo) {
}
/**
@@ -634,7 +657,7 @@
*/
public void onTvInteractiveAppServiceStateChanged(
@NonNull String iAppServiceId,
- @TvInteractiveAppInfo.InteractiveAppType int type,
+ @TvInteractiveAppServiceInfo.InteractiveAppType int type,
@ServiceState int state,
@ErrorCode int err) {
}
@@ -680,11 +703,12 @@
});
}
- public void postTvInteractiveAppInfoUpdated(final TvInteractiveAppInfo iAppInfo) {
+ public void postTvInteractiveAppServiceInfoUpdated(
+ final TvInteractiveAppServiceInfo iAppInfo) {
mExecutor.execute(new Runnable() {
@Override
public void run() {
- mCallback.onTvInteractiveAppInfoUpdated(iAppInfo);
+ mCallback.onTvInteractiveAppServiceInfoUpdated(iAppInfo);
}
});
}
@@ -737,11 +761,11 @@
/**
* Returns the complete list of TV Interactive App service on the system.
*
- * @return List of {@link TvInteractiveAppInfo} for each TV Interactive App service that
+ * @return List of {@link TvInteractiveAppServiceInfo} for each TV Interactive App service that
* describes its meta information.
*/
@NonNull
- public List<TvInteractiveAppInfo> getTvInteractiveAppServiceList() {
+ public List<TvInteractiveAppServiceInfo> getTvInteractiveAppServiceList() {
try {
return mService.getTvInteractiveAppServiceList(mUserId);
} catch (RemoteException e) {
@@ -750,22 +774,11 @@
}
/**
- * Prepares TV Interactive App service environment for the given type.
- */
- public void prepare(@NonNull String tvIAppServiceId, int type) {
- try {
- mService.prepare(tvIAppServiceId, type, mUserId);
- } catch (RemoteException e) {
- throw e.rethrowFromSystemServer();
- }
- }
-
- /**
* Registers an Android application link info record which can be used to launch the specific
* Android application by TV interactive App RTE.
*
* @param tvIAppServiceId The ID of TV interactive service which the command to be sent to. The
- * ID can be found in {@link TvInputInfo#getId()}.
+ * ID can be found in {@link TvInteractiveAppServiceInfo#getId()}.
* @param appLinkInfo The Android application link info record to be registered.
*/
public void registerAppLinkInfo(
@@ -782,7 +795,7 @@
* Android application by TV interactive App RTE.
*
* @param tvIAppServiceId The ID of TV interactive service which the command to be sent to. The
- * ID can be found in {@link TvInputInfo#getId()}.
+ * ID can be found in {@link TvInteractiveAppServiceInfo#getId()}.
* @param appLinkInfo The Android application link info record to be unregistered.
*/
public void unregisterAppLinkInfo(
@@ -798,7 +811,7 @@
* Sends app link command.
*
* @param tvIAppServiceId The ID of TV interactive service which the command to be sent to. The
- * ID can be found in {@link TvInputInfo#getId()}.
+ * ID can be found in {@link TvInteractiveAppServiceInfo#getId()}.
* @param command The command to be sent.
*/
public void sendAppLinkCommand(@NonNull String tvIAppServiceId, @NonNull Bundle command) {
@@ -1022,6 +1035,18 @@
}
}
+ void sendSigningResult(@NonNull String signingId, @NonNull byte[] result) {
+ if (mToken == null) {
+ Log.w(TAG, "The session has been already released");
+ return;
+ }
+ try {
+ mService.sendSigningResult(mToken, signingId, result, mUserId);
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+
/**
* Sets the {@link android.view.Surface} for this session.
*
@@ -1655,6 +1680,15 @@
});
}
+ void postRequestSigning(String id, String algorithm, String alias, byte[] data) {
+ mHandler.post(new Runnable() {
+ @Override
+ public void run() {
+ mSessionCallback.onRequestSigning(mSession, id, algorithm, alias, data);
+ }
+ });
+ }
+
void postAdRequest(final AdRequest request) {
mHandler.post(new Runnable() {
@Override
@@ -1792,12 +1826,27 @@
* called.
*
* @param session A {@link TvInteractiveAppService.Session} associated with this callback.
- * @hide
*/
public void onRequestCurrentTvInputId(Session session) {
}
/**
+ * This is called when
+ * {@link TvInteractiveAppService.Session#requestSigning(String, String, String, byte[])} is
+ * called.
+ *
+ * @param session A {@link TvInteractiveAppService.Session} associated with this callback.
+ * @param signingId the ID to identify the request.
+ * @param algorithm the standard name of the signature algorithm requested, such as
+ * MD5withRSA, SHA256withDSA, etc.
+ * @param alias the alias of the corresponding {@link java.security.KeyStore}.
+ * @param data the original bytes to be signed.
+ */
+ public void onRequestSigning(
+ Session session, String signingId, String algorithm, String alias, byte[] data) {
+ }
+
+ /**
* This is called when {@link TvInteractiveAppService.Session#notifySessionStateChanged} is
* called.
*
diff --git a/media/java/android/media/tv/interactive/TvInteractiveAppService.java b/media/java/android/media/tv/interactive/TvInteractiveAppService.java
index d22fd83..b103b10 100755
--- a/media/java/android/media/tv/interactive/TvInteractiveAppService.java
+++ b/media/java/android/media/tv/interactive/TvInteractiveAppService.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2021 The Android Open Source Project
+ * Copyright 2021 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -20,6 +20,7 @@
import android.annotation.MainThread;
import android.annotation.NonNull;
import android.annotation.Nullable;
+import android.annotation.Px;
import android.annotation.SdkConstant;
import android.annotation.StringDef;
import android.annotation.SuppressLint;
@@ -217,11 +218,6 @@
}
@Override
- public void prepare(int type) {
- onPrepare(type);
- }
-
- @Override
public void registerAppLinkInfo(AppLinkInfo appLinkInfo) {
onRegisterAppLinkInfo(appLinkInfo);
}
@@ -240,11 +236,6 @@
}
/**
- * Prepares TV Interactive App service for the given type.
- */
- public abstract void onPrepare(@TvInteractiveAppInfo.InteractiveAppType int type);
-
- /**
* Called when a request to register an Android application link info record is received.
*/
public void onRegisterAppLinkInfo(@NonNull AppLinkInfo appLinkInfo) {
@@ -277,7 +268,7 @@
@Nullable
public abstract Session onCreateSession(
@NonNull String iAppServiceId,
- @TvInteractiveAppInfo.InteractiveAppType int type);
+ @TvInteractiveAppServiceInfo.InteractiveAppType int type);
/**
* Notifies the system when the state of the interactive app RTE has been changed.
@@ -289,7 +280,7 @@
* {@link TvInteractiveAppManager#SERVICE_STATE_ERROR}.
*/
public final void notifyStateChanged(
- @TvInteractiveAppInfo.InteractiveAppType int type,
+ @TvInteractiveAppServiceInfo.InteractiveAppType int type,
@TvInteractiveAppManager.ServiceState int state,
@TvInteractiveAppManager.ErrorCode int error) {
SomeArgs args = SomeArgs.obtain();
@@ -373,6 +364,15 @@
}
/**
+ * Returns {@code true} if media view is enabled, {@code false} otherwise.
+ *
+ * @see #setMediaViewEnabled(boolean)
+ */
+ public boolean isMediaViewEnabled() {
+ return mMediaViewEnabled;
+ }
+
+ /**
* Starts TvInteractiveAppService session.
*/
public void onStartInteractiveApp() {
@@ -397,9 +397,10 @@
* no matter if it's created successfully or not.
*
* @see #notifyBiInteractiveAppCreated(Uri, String)
- * @see #onDestroyBiInteractiveApp(String)
+ * @see #onDestroyBiInteractiveAppRequest(String)
*/
- public void onCreateBiInteractiveApp(@NonNull Uri biIAppUri, @Nullable Bundle params) {
+ public void onCreateBiInteractiveAppRequest(
+ @NonNull Uri biIAppUri, @Nullable Bundle params) {
}
@@ -407,11 +408,11 @@
* Destroys broadcast-independent(BI) interactive application.
*
* @param biIAppId the BI interactive app ID from
- * {@link #onCreateBiInteractiveApp(Uri, Bundle)}}
+ * {@link #onCreateBiInteractiveAppRequest(Uri, Bundle)}
*
- * @see #onCreateBiInteractiveApp(Uri, Bundle)
+ * @see #onCreateBiInteractiveAppRequest(Uri, Bundle)
*/
- public void onDestroyBiInteractiveApp(@NonNull String biIAppId) {
+ public void onDestroyBiInteractiveAppRequest(@NonNull String biIAppId) {
}
/**
@@ -435,6 +436,8 @@
/**
* Receives current stream volume.
+ *
+ * @param volume a volume value between {@code 0.0f} and {@code 1.0f}, inclusive.
*/
public void onStreamVolume(float volume) {
}
@@ -452,6 +455,17 @@
}
/**
+ * Receives signing result.
+ * @param signingId the ID to identify the request. It's the same as the corresponding ID in
+ * {@link Session#requestSigning(String, String, String, byte[])}
+ * @param result the signed result.
+ *
+ * @see #requestSigning(String, String, String, byte[])
+ */
+ public void onSigningResult(@NonNull String signingId, @NonNull byte[] result) {
+ }
+
+ /**
* Called when the application sets the surface.
*
* <p>The TV Interactive App service should render interactive app UI onto the given
@@ -484,10 +498,10 @@
* containing {@link TvInteractiveAppView}. Note that the size of the underlying surface can
* be different if the surface was changed by calling {@link #layoutSurface}.
*
- * @param width The width of the media view.
- * @param height The height of the media view.
+ * @param width The width of the media view, in pixels.
+ * @param height The height of the media view, in pixels.
*/
- public void onMediaViewSizeChanged(int width, int height) {
+ public void onMediaViewSizeChanged(@Px int width, @Px int height) {
}
/**
@@ -877,6 +891,47 @@
}
/**
+ * Requests signing of the given data.
+ *
+ * <p>This is used when the corresponding server of the broadcast-independent interactive
+ * app requires signing during handshaking, and the interactive app service doesn't have
+ * the built-in private key. The private key is provided by the content providers and
+ * pre-built in the related app, such as TV app.
+ *
+ * @param signingId the ID to identify the request. When a result is received, this ID can
+ * be used to correlate the result with the request.
+ * @param algorithm the standard name of the signature algorithm requested, such as
+ * MD5withRSA, SHA256withDSA, etc. The name is from standards like
+ * FIPS PUB 186-4 and PKCS #1.
+ * @param alias the alias of the corresponding {@link java.security.KeyStore}.
+ * @param data the original bytes to be signed.
+ *
+ * @see #onSigningResult(String, byte[])
+ * @see TvInteractiveAppView#createBiInteractiveApp(Uri, Bundle)
+ * @see TvInteractiveAppView#BI_INTERACTIVE_APP_KEY_ALIAS
+ */
+ @CallSuper
+ public void requestSigning(@NonNull String signingId, @NonNull String algorithm,
+ @NonNull String alias, @NonNull byte[] data) {
+ executeOrPostRunnableOnMainThread(new Runnable() {
+ @MainThread
+ @Override
+ public void run() {
+ try {
+ if (DEBUG) {
+ Log.d(TAG, "requestSigning");
+ }
+ if (mSessionCallback != null) {
+ mSessionCallback.onRequestSigning(signingId, algorithm, alias, data);
+ }
+ } catch (RemoteException e) {
+ Log.w(TAG, "error in requestSigning", e);
+ }
+ }
+ });
+ }
+
+ /**
* Sends an advertisement request to be processed by the related TV input.
*
* @param request The advertisement request
@@ -914,11 +969,11 @@
}
void createBiInteractiveApp(@NonNull Uri biIAppUri, @Nullable Bundle params) {
- onCreateBiInteractiveApp(biIAppUri, params);
+ onCreateBiInteractiveAppRequest(biIAppUri, params);
}
void destroyBiInteractiveApp(@NonNull String biIAppId) {
- onDestroyBiInteractiveApp(biIAppId);
+ onDestroyBiInteractiveAppRequest(biIAppId);
}
void setTeletextAppEnabled(boolean enable) {
@@ -945,6 +1000,10 @@
onCurrentTvInputId(inputId);
}
+ void sendSigningResult(String signingId, byte[] result) {
+ onSigningResult(signingId, result);
+ }
+
void release() {
onRelease();
if (mSurface != null) {
@@ -1074,7 +1133,7 @@
* @param biIAppId BI interactive app ID, which can be used to destroy the BI interactive
* app. {@code null} if it's not created successfully.
*
- * @see #onCreateBiInteractiveApp(Uri, Bundle)
+ * @see #onCreateBiInteractiveAppRequest(Uri, Bundle)
*/
@CallSuper
public final void notifyBiInteractiveAppCreated(
@@ -1413,6 +1472,11 @@
}
@Override
+ public void sendSigningResult(@NonNull String signingId, @NonNull byte[] result) {
+ mSessionImpl.sendSigningResult(signingId, result);
+ }
+
+ @Override
public void release() {
mSessionImpl.scheduleMediaViewCleanup();
mSessionImpl.release();
diff --git a/media/java/android/media/tv/interactive/TvInteractiveAppInfo.aidl b/media/java/android/media/tv/interactive/TvInteractiveAppServiceInfo.aidl
similarity index 86%
rename from media/java/android/media/tv/interactive/TvInteractiveAppInfo.aidl
rename to media/java/android/media/tv/interactive/TvInteractiveAppServiceInfo.aidl
index 5e15016..4b6127c 100644
--- a/media/java/android/media/tv/interactive/TvInteractiveAppInfo.aidl
+++ b/media/java/android/media/tv/interactive/TvInteractiveAppServiceInfo.aidl
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2021 The Android Open Source Project
+ * Copyright 2021 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -16,4 +16,4 @@
package android.media.tv.interactive;
-parcelable TvInteractiveAppInfo;
\ No newline at end of file
+parcelable TvInteractiveAppServiceInfo;
\ No newline at end of file
diff --git a/media/java/android/media/tv/interactive/TvInteractiveAppInfo.java b/media/java/android/media/tv/interactive/TvInteractiveAppServiceInfo.java
similarity index 87%
rename from media/java/android/media/tv/interactive/TvInteractiveAppInfo.java
rename to media/java/android/media/tv/interactive/TvInteractiveAppServiceInfo.java
index 6103db0..3e08852 100644
--- a/media/java/android/media/tv/interactive/TvInteractiveAppInfo.java
+++ b/media/java/android/media/tv/interactive/TvInteractiveAppServiceInfo.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2021 The Android Open Source Project
+ * Copyright 2021 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -45,9 +45,9 @@
/**
* This class is used to specify meta information of a TV interactive app.
*/
-public final class TvInteractiveAppInfo implements Parcelable {
+public final class TvInteractiveAppServiceInfo implements Parcelable {
private static final boolean DEBUG = false;
- private static final String TAG = "TvInteractiveAppInfo";
+ private static final String TAG = "TvInteractiveAppServiceInfo";
private static final String XML_START_TAG_NAME = "tv-interactive-app";
@@ -71,7 +71,13 @@
private final String mId;
private int mTypes;
- public TvInteractiveAppInfo(@NonNull Context context, @NonNull ComponentName component) {
+ /**
+ * Constructs a TvInteractiveAppServiceInfo object.
+ *
+ * @param context the application context
+ * @param component the component name of the TvInteractiveAppService
+ */
+ public TvInteractiveAppServiceInfo(@NonNull Context context, @NonNull ComponentName component) {
if (context == null) {
throw new IllegalArgumentException("context cannot be null.");
}
@@ -94,28 +100,28 @@
mId = id;
mTypes = toTypesFlag(types);
}
- private TvInteractiveAppInfo(ResolveInfo service, String id, int types) {
+ private TvInteractiveAppServiceInfo(ResolveInfo service, String id, int types) {
mService = service;
mId = id;
mTypes = types;
}
- private TvInteractiveAppInfo(@NonNull Parcel in) {
+ private TvInteractiveAppServiceInfo(@NonNull Parcel in) {
mService = ResolveInfo.CREATOR.createFromParcel(in);
mId = in.readString();
mTypes = in.readInt();
}
- public static final @NonNull Creator<TvInteractiveAppInfo> CREATOR =
- new Creator<TvInteractiveAppInfo>() {
+ public static final @NonNull Creator<TvInteractiveAppServiceInfo> CREATOR =
+ new Creator<TvInteractiveAppServiceInfo>() {
@Override
- public TvInteractiveAppInfo createFromParcel(Parcel in) {
- return new TvInteractiveAppInfo(in);
+ public TvInteractiveAppServiceInfo createFromParcel(Parcel in) {
+ return new TvInteractiveAppServiceInfo(in);
}
@Override
- public TvInteractiveAppInfo[] newArray(int size) {
- return new TvInteractiveAppInfo[size];
+ public TvInteractiveAppServiceInfo[] newArray(int size) {
+ return new TvInteractiveAppServiceInfo[size];
}
};
diff --git a/media/java/android/media/tv/interactive/TvInteractiveAppView.java b/media/java/android/media/tv/interactive/TvInteractiveAppView.java
index 773e54f..1df757b 100755
--- a/media/java/android/media/tv/interactive/TvInteractiveAppView.java
+++ b/media/java/android/media/tv/interactive/TvInteractiveAppView.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2021 The Android Open Source Project
+ * Copyright 2021 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -46,6 +46,7 @@
import android.view.ViewGroup;
import android.view.ViewRootImpl;
+import java.security.KeyStore;
import java.util.List;
import java.util.concurrent.Executor;
@@ -61,6 +62,41 @@
private static final int UNSET_TVVIEW_SUCCESS = 3;
private static final int UNSET_TVVIEW_FAIL = 4;
+ /**
+ * Used to share client {@link java.security.cert.Certificate} with
+ * {@link TvInteractiveAppService}.
+ * @see #createBiInteractiveApp(Uri, Bundle)
+ * @see java.security.cert.Certificate
+ */
+ public static final String BI_INTERACTIVE_APP_KEY_CERTIFICATE = "certificate";
+ /**
+ * Used to share the {@link KeyStore} alias with {@link TvInteractiveAppService}.
+ * @see #createBiInteractiveApp(Uri, Bundle)
+ * @see KeyStore#aliases()
+ */
+ public static final String BI_INTERACTIVE_APP_KEY_ALIAS = "alias";
+ /**
+ * Used to share the {@link java.security.PrivateKey} with {@link TvInteractiveAppService}.
+ * <p>The private key is optional. It is used to encrypt data when necessary.
+ *
+ * @see #createBiInteractiveApp(Uri, Bundle)
+ * @see java.security.PrivateKey
+ */
+ public static final String BI_INTERACTIVE_APP_KEY_PRIVATE_KEY = "private_key";
+ /**
+ * Additional HTTP headers to be used by {@link TvInteractiveAppService} to load the
+ * broadcast-independent interactive application.
+ * @see #createBiInteractiveApp(Uri, Bundle)
+ */
+ public static final String BI_INTERACTIVE_APP_KEY_HTTP_ADDITIONAL_HEADERS =
+ "http_additional_headers";
+ /**
+ * HTTP user agent to be used by {@link TvInteractiveAppService} for broadcast-independent
+ * interactive application.
+ * @see #createBiInteractiveApp(Uri, Bundle)
+ */
+ public static final String BI_INTERACTIVE_APP_KEY_HTTP_USER_AGENT = "http_user_agent";
+
private final TvInteractiveAppManager mTvInteractiveAppManager;
private final Handler mHandler = new Handler();
private final Object mCallbackLock = new Object();
@@ -148,12 +184,14 @@
/**
* Sets the callback to be invoked when an event is dispatched to this TvInteractiveAppView.
*
- * @param callback The callback to receive events. A value of {@code null} removes the existing
- * callback.
+ * @param callback the callback to receive events. MUST NOT be {@code null}.
+ *
+ * @see #clearCallback()
*/
public void setCallback(
@NonNull @CallbackExecutor Executor executor,
@NonNull TvInteractiveAppCallback callback) {
+ com.android.internal.util.AnnotationValidations.validate(NonNull.class, null, callback);
synchronized (mCallbackLock) {
mCallbackExecutor = executor;
mCallback = callback;
@@ -162,6 +200,8 @@
/**
* Clears the callback.
+ *
+ * @see #setCallback(Executor, TvInteractiveAppCallback)
*/
public void clearCallback() {
synchronized (mCallbackLock) {
@@ -238,7 +278,9 @@
}
/**
- * Resets this TvInteractiveAppView.
+ * Resets this TvInteractiveAppView to release its resources.
+ *
+ * <p>It can be reused by call {@link #prepareInteractiveApp(String, int)}.
*/
public void reset() {
if (DEBUG) Log.d(TAG, "reset()");
@@ -364,6 +406,19 @@
mOnUnhandledInputEventListener = listener;
// TODO: handle CallbackExecutor
}
+
+ /**
+ * Gets the {@link OnUnhandledInputEventListener}.
+ * <p>Returns {@code null} if the listener is not set or is cleared.
+ *
+ * @see #setOnUnhandledInputEventListener(Executor, OnUnhandledInputEventListener)
+ * @see #clearOnUnhandledInputEventListener()
+ */
+ @Nullable
+ public OnUnhandledInputEventListener getOnUnhandledInputEventListener() {
+ return mOnUnhandledInputEventListener;
+ }
+
/**
* Clears the {@link OnUnhandledInputEventListener}.
*/
@@ -386,16 +441,17 @@
}
/**
- * Prepares the interactive application.
+ * Prepares the interactive application runtime environment of corresponding
+ * {@link TvInteractiveAppService}.
*
* @param iAppServiceId the interactive app service ID, which can be found in
- * {@link TvInteractiveAppInfo#getId()}.
+ * {@link TvInteractiveAppServiceInfo#getId()}.
*
* @see android.media.tv.interactive.TvInteractiveAppManager#getTvInteractiveAppServiceList()
*/
public void prepareInteractiveApp(
@NonNull String iAppServiceId,
- @TvInteractiveAppInfo.InteractiveAppType int type) {
+ @TvInteractiveAppServiceInfo.InteractiveAppType int type) {
// TODO: document and handle the cases that this method is called multiple times.
if (DEBUG) {
Log.d(TAG, "prepareInteractiveApp");
@@ -432,6 +488,8 @@
/**
* Resets the interactive application.
+ *
+ * <p>This releases the resources of the corresponding {@link TvInteractiveAppService.Session}.
*/
public void resetInteractiveApp() {
if (DEBUG) {
@@ -471,6 +529,8 @@
/**
* Sends stream volume to related TV interactive app.
+ *
+ * @param volume a volume value between {@code 0.0f} and {@code 1.0f}, inclusive.
*/
public void sendStreamVolume(float volume) {
if (DEBUG) {
@@ -509,6 +569,27 @@
}
}
+ /**
+ * Sends signing result to related TV interactive app.
+ *
+ * <p>This is used when the corresponding server of the broadcast-independent interactive
+ * app requires signing during handshaking, and the interactive app service doesn't have
+ * the built-in private key. The private key is provided by the content providers and
+ * pre-built in the related app, such as TV app.
+ *
+ * @param signingId the ID to identify the request. It's the same as the corresponding ID in
+ * {@link TvInteractiveAppService.Session#requestSigning(String, String, String, byte[])}
+ * @param result the signed result.
+ */
+ public void sendSigningResult(@NonNull String signingId, @NonNull byte[] result) {
+ if (DEBUG) {
+ Log.d(TAG, "sendSigningResult");
+ }
+ if (mSession != null) {
+ mSession.sendSigningResult(signingId, result);
+ }
+ }
+
private void resetInternal() {
mSessionCallback = null;
if (mSession != null) {
@@ -527,7 +608,14 @@
* <p>{@link TvInteractiveAppCallback#onBiInteractiveAppCreated(String, Uri, String)} will be
* called for the result.
*
+ * @param biIAppUri URI associated this BI interactive app.
+ * @param params optional parameters for broadcast-independent interactive application, such as
+ * {@link #BI_INTERACTIVE_APP_KEY_CERTIFICATE}.
+ *
* @see TvInteractiveAppCallback#onBiInteractiveAppCreated(String, Uri, String)
+ * @see #BI_INTERACTIVE_APP_KEY_CERTIFICATE
+ * @see #BI_INTERACTIVE_APP_KEY_HTTP_ADDITIONAL_HEADERS
+ * @see #BI_INTERACTIVE_APP_KEY_HTTP_USER_AGENT
*/
public void createBiInteractiveApp(@NonNull Uri biIAppUri, @Nullable Bundle params) {
if (DEBUG) {
@@ -721,6 +809,22 @@
public void onRequestCurrentTvInputId(@NonNull String iAppServiceId) {
}
+ /**
+ * This is called when
+ * {@link TvInteractiveAppService.Session#requestSigning(String, String, String, byte[])} is
+ * called.
+ *
+ * @param iAppServiceId The ID of the TV interactive app service bound to this view.
+ * @param signingId the ID to identify the request.
+ * @param algorithm the standard name of the signature algorithm requested, such as
+ * MD5withRSA, SHA256withDSA, etc.
+ * @param alias the alias of the corresponding {@link java.security.KeyStore}.
+ * @param data the original bytes to be signed.
+ */
+ public void onRequestSigning(@NonNull String iAppServiceId, @NonNull String signingId,
+ @NonNull String algorithm, @NonNull String alias, @NonNull byte[] data) {
+ }
+
}
/**
@@ -1027,5 +1131,20 @@
mCallback.onRequestCurrentTvInputId(mIAppServiceId);
}
}
+
+ @Override
+ public void onRequestSigning(
+ Session session, String id, String algorithm, String alias, byte[] data) {
+ if (DEBUG) {
+ Log.d(TAG, "onRequestSigning");
+ }
+ if (this != mSessionCallback) {
+ Log.w(TAG, "onRequestSigning - session not created");
+ return;
+ }
+ if (mCallback != null) {
+ mCallback.onRequestSigning(mIAppServiceId, id, algorithm, alias, data);
+ }
+ }
}
}
diff --git a/packages/BackupRestoreConfirmation/res/values/strings.xml b/packages/BackupRestoreConfirmation/res/values/strings.xml
index 3fb3fd4..5c90fd0 100644
--- a/packages/BackupRestoreConfirmation/res/values/strings.xml
+++ b/packages/BackupRestoreConfirmation/res/values/strings.xml
@@ -44,8 +44,6 @@
<string name="backup_enc_password_text">Please enter a password to use for encrypting the full backup data. If this is left blank, your current backup password will be used:</string>
<!-- Text for message to user that they may optionally supply an encryption password to use for a full backup operation. -->
<string name="backup_enc_password_optional">If you wish to encrypt the full backup data, enter a password below:</string>
- <!-- Text for message to user that they must supply an encryption password to use for a full backup operation because their phone is locked. -->
- <string name="backup_enc_password_required">Since your device is encrypted, you are required to encrypt your backup. Please enter a password below:</string>
<!-- Text for message to user when performing a full restore operation, explaining that they must enter the password originally used to encrypt the full backup data. -->
<string name="restore_enc_password_text">If the restore data is encrypted, please enter the password below:</string>
diff --git a/packages/BackupRestoreConfirmation/src/com/android/backupconfirm/BackupRestoreConfirmation.java b/packages/BackupRestoreConfirmation/src/com/android/backupconfirm/BackupRestoreConfirmation.java
index d6b6bf8..3c790f0 100644
--- a/packages/BackupRestoreConfirmation/src/com/android/backupconfirm/BackupRestoreConfirmation.java
+++ b/packages/BackupRestoreConfirmation/src/com/android/backupconfirm/BackupRestoreConfirmation.java
@@ -27,8 +27,6 @@
import android.os.Message;
import android.os.RemoteException;
import android.os.ServiceManager;
-import android.os.storage.IStorageManager;
-import android.os.storage.StorageManager;
import android.text.Editable;
import android.text.TextWatcher;
import android.util.Slog;
@@ -66,10 +64,8 @@
Handler mHandler;
IBackupManager mBackupManager;
- IStorageManager mStorageManager;
FullObserver mObserver;
int mToken;
- boolean mIsEncrypted;
boolean mDidAcknowledge;
String mAction;
@@ -144,7 +140,6 @@
}
mBackupManager = IBackupManager.Stub.asInterface(ServiceManager.getService(Context.BACKUP_SERVICE));
- mStorageManager = IStorageManager.Stub.asInterface(ServiceManager.getService("mount"));
mHandler = new ObserverHandler(getApplicationContext());
final Object oldObserver = getLastNonConfigurationInstance();
@@ -248,20 +243,13 @@
mDenyButton.setEnabled(!mDidAcknowledge);
}
- // We vary the password prompt depending on whether one is predefined, and whether
- // the device is encrypted.
- mIsEncrypted = deviceIsEncrypted();
+ // We vary the password prompt depending on whether one is predefined.
if (!haveBackupPassword()) {
curPwDesc.setVisibility(View.GONE);
mCurPassword.setVisibility(View.GONE);
if (layoutId == R.layout.confirm_backup) {
TextView encPwDesc = findViewById(R.id.enc_password_desc);
- if (mIsEncrypted) {
- encPwDesc.setText(R.string.backup_enc_password_required);
- monitorEncryptionPassword();
- } else {
- encPwDesc.setText(R.string.backup_enc_password_optional);
- }
+ encPwDesc.setText(R.string.backup_enc_password_optional);
}
}
}
@@ -312,20 +300,6 @@
}
}
- boolean deviceIsEncrypted() {
- try {
- return mStorageManager.getEncryptionState()
- != StorageManager.ENCRYPTION_STATE_NONE
- && mStorageManager.getPasswordType()
- != StorageManager.CRYPT_TYPE_DEFAULT;
- } catch (Exception e) {
- // If we can't talk to the storagemanager service we have a serious problem; fail
- // "secure" i.e. assuming that the device is encrypted.
- Slog.e(TAG, "Unable to communicate with storagemanager service: " + e.getMessage());
- return true;
- }
- }
-
boolean haveBackupPassword() {
try {
return mBackupManager.hasBackupPassword();
diff --git a/packages/CompanionDeviceManager/res/color/selector.xml b/packages/CompanionDeviceManager/res/color/selector.xml
index 56e5dca..aebc5d5 100644
--- a/packages/CompanionDeviceManager/res/color/selector.xml
+++ b/packages/CompanionDeviceManager/res/color/selector.xml
@@ -1,3 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
<!--
~ Copyright (C) 2022 The Android Open Source Project
~
diff --git a/packages/CompanionDeviceManager/res/drawable/btn_negative_multiple_devices.xml b/packages/CompanionDeviceManager/res/drawable/btn_negative_multiple_devices.xml
index ece7bba..ebe16a7 100644
--- a/packages/CompanionDeviceManager/res/drawable/btn_negative_multiple_devices.xml
+++ b/packages/CompanionDeviceManager/res/drawable/btn_negative_multiple_devices.xml
@@ -1,3 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
<!--
~ Copyright (C) 2022 The Android Open Source Project
~
diff --git a/packages/CompanionDeviceManager/res/drawable/btn_negative_top.xml b/packages/CompanionDeviceManager/res/drawable/btn_negative_top.xml
index 7df92bb..3cd7929 100644
--- a/packages/CompanionDeviceManager/res/drawable/btn_negative_top.xml
+++ b/packages/CompanionDeviceManager/res/drawable/btn_negative_top.xml
@@ -1,3 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
<!--
~ Copyright (C) 2022 The Android Open Source Project
~
@@ -17,6 +18,6 @@
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<solid android:color="@android:color/system_accent1_100"/>
- <corners android:topLeftRadius="12dp" android:topRightRadius="12dp"
- android:bottomLeftRadius="4dp" android:bottomRightRadius="4dp"/>
+ <corners android:topLeftRadius="4dp" android:topRightRadius="4dp"
+ android:bottomLeftRadius="12dp" android:bottomRightRadius="12dp"/>
</shape>
diff --git a/packages/CompanionDeviceManager/res/drawable/btn_positive_bottom.xml b/packages/CompanionDeviceManager/res/drawable/btn_positive_bottom.xml
index 55e96f6..2cff473 100644
--- a/packages/CompanionDeviceManager/res/drawable/btn_positive_bottom.xml
+++ b/packages/CompanionDeviceManager/res/drawable/btn_positive_bottom.xml
@@ -1,3 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
<!--
~ Copyright (C) 2022 The Android Open Source Project
~
@@ -17,6 +18,6 @@
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<solid android:color="@android:color/system_accent1_100"/>
- <corners android:topLeftRadius="4dp" android:topRightRadius="4dp"
- android:bottomLeftRadius="12dp" android:bottomRightRadius="12dp"/>
+ <corners android:topLeftRadius="12dp" android:topRightRadius="12dp"
+ android:bottomLeftRadius="4dp" android:bottomRightRadius="4dp"/>
</shape>
diff --git a/packages/CompanionDeviceManager/res/drawable/helper_ok_button.xml b/packages/CompanionDeviceManager/res/drawable/helper_ok_button.xml
index f9ec5d0..8e92051 100644
--- a/packages/CompanionDeviceManager/res/drawable/helper_ok_button.xml
+++ b/packages/CompanionDeviceManager/res/drawable/helper_ok_button.xml
@@ -1,3 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
<!--
~ Copyright (C) 2022 The Android Open Source Project
~
diff --git a/packages/CompanionDeviceManager/res/drawable/ic_apps.xml b/packages/CompanionDeviceManager/res/drawable/ic_apps.xml
index 93a0cba..d1ec863 100644
--- a/packages/CompanionDeviceManager/res/drawable/ic_apps.xml
+++ b/packages/CompanionDeviceManager/res/drawable/ic_apps.xml
@@ -1,3 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
<!--
~ Copyright (C) 2022 The Android Open Source Project
~
diff --git a/packages/CompanionDeviceManager/res/drawable/ic_device_other.xml b/packages/CompanionDeviceManager/res/drawable/ic_device_other.xml
index f8515c3..2a8eb24 100644
--- a/packages/CompanionDeviceManager/res/drawable/ic_device_other.xml
+++ b/packages/CompanionDeviceManager/res/drawable/ic_device_other.xml
@@ -1,3 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
<!--
~ Copyright (C) 2022 The Android Open Source Project
~
diff --git a/packages/CompanionDeviceManager/res/drawable/ic_notifications.xml b/packages/CompanionDeviceManager/res/drawable/ic_notifications.xml
index 4ac4d04..e5825bc 100644
--- a/packages/CompanionDeviceManager/res/drawable/ic_notifications.xml
+++ b/packages/CompanionDeviceManager/res/drawable/ic_notifications.xml
@@ -1,3 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
<!--
~ Copyright (C) 2022 The Android Open Source Project
~
diff --git a/packages/CompanionDeviceManager/res/drawable/ic_storage.xml b/packages/CompanionDeviceManager/res/drawable/ic_storage.xml
index d8b7f59..406a3b5 100644
--- a/packages/CompanionDeviceManager/res/drawable/ic_storage.xml
+++ b/packages/CompanionDeviceManager/res/drawable/ic_storage.xml
@@ -1,3 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
<!--
~ Copyright (C) 2022 The Android Open Source Project
~
diff --git a/packages/CompanionDeviceManager/res/drawable/ic_watch.xml b/packages/CompanionDeviceManager/res/drawable/ic_watch.xml
index 44a40b9f..d7a28d9 100644
--- a/packages/CompanionDeviceManager/res/drawable/ic_watch.xml
+++ b/packages/CompanionDeviceManager/res/drawable/ic_watch.xml
@@ -1,3 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
<!--
~ Copyright (C) 2022 The Android Open Source Project
~
diff --git a/packages/CompanionDeviceManager/res/layout/activity_confirmation.xml b/packages/CompanionDeviceManager/res/layout/activity_confirmation.xml
index 8eec33a..c37054e 100644
--- a/packages/CompanionDeviceManager/res/layout/activity_confirmation.xml
+++ b/packages/CompanionDeviceManager/res/layout/activity_confirmation.xml
@@ -1,6 +1,5 @@
<?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");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
@@ -20,35 +19,26 @@
<!-- A header for selfManaged devices only. -->
<include layout="@layout/vendor_header" />
+ <!-- Do NOT change the ID of the root LinearLayout above: it's referenced in CTS tests. -->
+
<ImageView
android:id="@+id/profile_icon"
android:layout_width="match_parent"
android:layout_height="32dp"
android:gravity="center"
- android:layout_marginBottom="12dp"
- android:layout_marginTop="1dp"
+ android:layout_marginTop="18dp"
android:tint="@android:color/system_accent1_600"/>
- <!-- Do NOT change the ID of the root LinearLayout above: it's referenced in CTS tests. -->
+ <LinearLayout style="@style/Description">
+ <TextView
+ android:id="@+id/title"
+ style="@style/DescriptionTitle" />
- <TextView
- android:id="@+id/title"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:gravity="center"
- android:paddingHorizontal="12dp"
- android:layout_marginBottom="12dp"
- style="@*android:style/TextAppearance.Widget.Toolbar.Title" />
+ <TextView
+ android:id="@+id/summary"
+ style="@style/DescriptionSummary" />
- <TextView
- android:id="@+id/summary"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:layout_marginTop="12dp"
- android:layout_marginBottom="12dp"
- android:gravity="center"
- android:textColor="?android:attr/textColorSecondary"
- android:textSize="14sp" />
+ </LinearLayout>
<RelativeLayout
android:layout_width="match_parent"
@@ -59,18 +49,20 @@
android:id="@+id/multiple_device_list"
android:layout_width="match_parent"
android:layout_height="wrap_content"
+ android:layout_marginTop="12dp"
+ android:layout_marginBottom="12dp"
android:orientation="vertical"
android:visibility="gone">
<View
android:id="@+id/border_top"
- android:layout_marginTop="12dp"
style="@style/DeviceListBorder" />
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/device_list"
android:layout_width="match_parent"
android:scrollbars="vertical"
+ android:layout_marginBottom="12dp"
android:layout_height="200dp" />
<View
@@ -84,35 +76,56 @@
android:layout_width="match_parent"
android:layout_height="wrap_content" />
+ <ProgressBar
+ android:id="@+id/spinner"
+ android:layout_width="56dp"
+ android:layout_height="56dp"
+ android:layout_centerInParent="true"
+ android:indeterminate="true"
+ android:tint="@android:color/system_accent1_600"
+ android:visibility="gone"
+ style="?android:attr/progressBarStyleLarge" />
+
</RelativeLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
+ android:gravity="center"
android:orientation="vertical"
- android:layout_marginTop="24dp">
+ android:layout_marginTop="16dp">
<!-- Do NOT change the IDs of the buttons: they are referenced in CTS tests. -->
<Button
- android:id="@+id/btn_negative"
- style="@style/NegativeButton"
- android:text="@string/consent_no" />
-
- <Button
android:id="@+id/btn_positive"
style="@style/PositiveButton"
android:text="@string/consent_yes" />
<Button
- android:id="@+id/btn_negative_multiple_devices"
- android:layout_marginLeft="170dp"
- android:layout_marginBottom="10dp"
- style="@style/NegativeButtonMultipleDevices"
- android:textColor = "?android:textColorPrimary"
- android:visibility="gone"
+ android:id="@+id/btn_negative"
+ android:layout_marginBottom="12dp"
+ style="@style/NegativeButton"
android:text="@string/consent_no" />
</LinearLayout>
+ <LinearLayout
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:gravity="bottom|right"
+ android:orientation="vertical"
+ android:layout_marginRight="16dp"
+ android:layout_marginBottom="16dp">
+
+ <!-- Do NOT change the IDs of the buttons: they are referenced in CTS tests. -->
+
+ <Button
+ android:id="@+id/btn_negative_multiple_devices"
+ style="@style/NegativeButtonMultipleDevices"
+ android:textColor="?android:textColorPrimary"
+ android:visibility="gone"
+ android:text="@string/consent_no" />
+ </LinearLayout>
+
</LinearLayout>
\ No newline at end of file
diff --git a/packages/CompanionDeviceManager/res/layout/data_transfer_confirmation.xml b/packages/CompanionDeviceManager/res/layout/data_transfer_confirmation.xml
index 7c50814..3d08493 100644
--- a/packages/CompanionDeviceManager/res/layout/data_transfer_confirmation.xml
+++ b/packages/CompanionDeviceManager/res/layout/data_transfer_confirmation.xml
@@ -15,54 +15,42 @@
~ limitations under the License.
-->
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
- android:id="@+id/activity_confirmation"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:background="@drawable/dialog_background"
- android:elevation="16dp"
- android:maxHeight="400dp"
- android:orientation="vertical"
- android:padding="18dp"
- android:layout_gravity="center">
+ android:id="@+id/data_transfer_confirmation"
+ style="@style/ContainerLayout">
<!-- Do NOT change the ID of the root LinearLayout above: it's referenced in CTS tests. -->
- <TextView
- android:id="@+id/title"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:gravity="center"
- android:paddingHorizontal="12dp"
- style="@*android:style/TextAppearance.Widget.Toolbar.Title"/>
+ <LinearLayout style="@style/Description">
+ <TextView
+ android:id="@+id/title"
+ style="@style/DescriptionTitle" />
- <TextView
- android:id="@+id/summary"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:layout_marginTop="12dp"
- android:layout_marginBottom="12dp"
- android:gravity="center"
- android:textColor="?android:attr/textColorSecondary"
- android:textSize="14sp" />
+ <TextView
+ android:id="@+id/summary"
+ style="@style/DescriptionSummary" />
+
+ </LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
+ android:gravity="center"
android:orientation="vertical"
- android:layout_marginTop="24dp">
+ android:layout_marginTop="16dp">
<!-- Do NOT change the IDs of the buttons: they are referenced in CTS tests. -->
<Button
- android:id="@+id/btn_negative"
- style="@style/NegativeButton"
- android:text="@string/consent_no" />
-
- <Button
android:id="@+id/btn_positive"
style="@style/PositiveButton"
android:text="@string/consent_yes" />
+ <Button
+ android:id="@+id/btn_negative"
+ android:layout_marginBottom="12dp"
+ style="@style/NegativeButton"
+ android:text="@string/consent_no" />
+
</LinearLayout>
</LinearLayout>
\ No newline at end of file
diff --git a/packages/CompanionDeviceManager/res/layout/helper_confirmation.xml b/packages/CompanionDeviceManager/res/layout/helper_confirmation.xml
index c177039..a22ca94 100644
--- a/packages/CompanionDeviceManager/res/layout/helper_confirmation.xml
+++ b/packages/CompanionDeviceManager/res/layout/helper_confirmation.xml
@@ -1,3 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
<!--
~ Copyright (C) 2022 The Android Open Source Project
~
@@ -17,6 +18,7 @@
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/helper_confirmation"
android:theme="@style/ChooserActivity"
+ android:padding="12dp"
style="@style/ContainerLayout">
<ImageView
@@ -24,8 +26,8 @@
android:layout_width="match_parent"
android:layout_height="32dp"
android:gravity="center"
- android:layout_marginBottom="12dp"
- android:layout_marginTop="1dp"/>
+ android:layout_marginTop="12dp"
+ android:layout_marginBottom="12dp"/>
<TextView
android:id="@+id/helper_title"
@@ -33,17 +35,18 @@
android:layout_height="wrap_content"
android:gravity="center"
android:paddingHorizontal="12dp"
- style="@*android:style/TextAppearance.Widget.Toolbar.Title"
- android:textSize="20sp" />
+ android:textColor="?android:attr/textColorPrimary"
+ android:textSize="22sp" />
<TextView
android:id="@+id/helper_summary"
android:layout_width="match_parent"
android:layout_height="wrap_content"
+ android:layout_marginLeft="24dp"
+ android:layout_marginRight="24dp"
android:layout_marginTop="12dp"
- android:layout_marginLeft="20dp"
android:layout_marginBottom="24dp"
- android:gravity="start"
+ android:gravity="center"
android:textColor="?android:attr/textColorSecondary"
android:textSize="14sp" />
@@ -51,6 +54,8 @@
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
+ android:layout_marginRight="12dp"
+ android:layout_marginBottom="12dp"
android:gravity="end">
<Button
diff --git a/packages/CompanionDeviceManager/res/layout/list_item_device.xml b/packages/CompanionDeviceManager/res/layout/list_item_device.xml
index 3c8a81f..eeb988f 100644
--- a/packages/CompanionDeviceManager/res/layout/list_item_device.xml
+++ b/packages/CompanionDeviceManager/res/layout/list_item_device.xml
@@ -28,6 +28,7 @@
android:id="@android:id/icon"
android:layout_width="24dp"
android:layout_height="24dp"
+ android:layout_marginLeft="24dp"
android:layout_marginRight="12dp"
android:tint="@android:color/system_accent1_600"/>
diff --git a/packages/CompanionDeviceManager/res/layout/list_item_permission.xml b/packages/CompanionDeviceManager/res/layout/list_item_permission.xml
index 79aa4e7..3dce38d 100644
--- a/packages/CompanionDeviceManager/res/layout/list_item_permission.xml
+++ b/packages/CompanionDeviceManager/res/layout/list_item_permission.xml
@@ -1,3 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
<!--
~ Copyright (C) 2022 The Android Open Source Project
~
@@ -19,13 +20,15 @@
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
- android:padding="5dp">
+ android:paddingLeft="32dp"
+ android:paddingRight="32dp"
+ android:paddingBottom="14dp">
<ImageView
android:id="@+id/permission_icon"
android:layout_width="24dp"
android:layout_height="24dp"
- android:layout_marginTop="7dp"
+ android:layout_marginTop="8dp"
android:layout_marginEnd="12dp"
android:tint="@android:color/system_accent1_600"
android:contentDescription="Permission Icon"/>
@@ -48,6 +51,7 @@
android:id="@+id/permission_summary"
android:layout_width="match_parent"
android:layout_height="wrap_content"
+ android:paddingRight="24dp"
android:textSize="14sp"
android:textColor="?android:attr/textColorSecondary"/>
diff --git a/packages/CompanionDeviceManager/res/layout/vendor_header.xml b/packages/CompanionDeviceManager/res/layout/vendor_header.xml
index d04eadf..5f6aa94 100644
--- a/packages/CompanionDeviceManager/res/layout/vendor_header.xml
+++ b/packages/CompanionDeviceManager/res/layout/vendor_header.xml
@@ -1,3 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
<!--
~ Copyright (C) 2022 The Android Open Source Project
~
@@ -21,7 +22,10 @@
android:layout_height="wrap_content"
android:orientation="horizontal"
android:layout_gravity="center"
- android:layout_marginBottom="16dp"
+ android:paddingTop="24dp"
+ android:paddingBottom="4dp"
+ android:paddingLeft="24dp"
+ android:paddingRight="24dp"
android:visibility="gone" >
<ImageView
@@ -42,7 +46,6 @@
style="?android:attr/actionOverflowButtonStyle"
android:layout_width="31dp"
android:layout_height="32dp"
- android:layout_marginLeft="100dp"
android:layout_alignParentRight="true" />
</RelativeLayout>
\ No newline at end of file
diff --git a/packages/CompanionDeviceManager/res/values-af/strings.xml b/packages/CompanionDeviceManager/res/values-af/strings.xml
index 2d8ef73..eec09d2 100644
--- a/packages/CompanionDeviceManager/res/values-af/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-af/strings.xml
@@ -22,18 +22,30 @@
<string name="chooser_title" msgid="2262294130493605839">"Kies \'n <xliff:g id="PROFILE_NAME">%1$s</xliff:g> om deur <strong><xliff:g id="APP_NAME">%2$s</xliff:g></strong> bestuur te word"</string>
<string name="summary_watch" product="default" msgid="7113724443198337683">"<xliff:g id="APP_NAME">%1$s</xliff:g> sal interaksie met jou kennisgewings mag hê en toegang kry tot jou Foon-, SMS-, Kontakte- en Kalender-toestemmings."</string>
<string name="summary_watch" product="tablet" msgid="7113724443198337683">"<xliff:g id="APP_NAME">%1$s</xliff:g> sal interaksie met jou kennisgewings mag hê en toegang kry tot jou Foon-, SMS-, Kontakte- en Kalender-toestemmings."</string>
- <string name="title_app_streaming" msgid="4459136600249308574">"Laat <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> toe om programme te stroom?"</string>
+ <string name="permission_apps" msgid="6142133265286656158">"Programme"</string>
+ <string name="permission_apps_summary" msgid="798718816711515431">"Stroom jou foon se programme"</string>
+ <string name="title_app_streaming" msgid="2270331024626446950">"Gee <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> toegang tot hierdie inligting op jou foon"</string>
<string name="summary_app_streaming" product="default" msgid="6105916810614498138">"Gee <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> afstandtoegang tot programme wat op <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong> geïnstalleer is wanneer hierdie foon aan die internet gekoppel is."</string>
<string name="summary_app_streaming" product="tablet" msgid="2996373715966272792">"Gee <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> afstandtoegang tot programme wat op <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong> geïnstalleer is wanneer hierdie tablet aan die internet gekoppel is."</string>
<string name="summary_app_streaming" product="device" msgid="7614171699434639963">"Gee <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> afstandtoegang tot programme wat op <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong> geïnstalleer is wanneer hierdie toestel aan die internet gekoppel is."</string>
+ <string name="helper_title_app_streaming" msgid="4151687003439969765">"Oorkruistoestel-dienste"</string>
+ <string name="helper_summary_app_streaming" msgid="5344341720432827388">"Hierdie diens word gebruik om programme tussen jou toestelle te stroom"</string>
<string name="title_automotive_projection" msgid="3296005598978412847"></string>
<string name="summary_automotive_projection" msgid="8683801274662496164"></string>
<string name="title_computer" msgid="4693714143506569253">"Gee <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> toegang tot hierdie inligting op jou foon"</string>
<string name="summary_computer" msgid="3798467601598297062"></string>
+ <string name="permission_notification" msgid="693762568127741203">"Kennisgewings"</string>
+ <string name="permission_notification_summary" msgid="4398672775023193663">"Kan alle kennisgewings lees, insluitend inligting soos kontakte, boodskappe en foto\'s"</string>
+ <string name="permission_storage" msgid="6831099350839392343">"Foto\'s en media"</string>
+ <string name="permission_storage_summary" msgid="3918240895519506417"></string>
+ <string name="helper_title_computer" msgid="4671071173916176037">"Google Play Dienste"</string>
+ <string name="helper_summary_computer" product="default" msgid="467996390095403648">"Hierdie diens deel foto\'s, media en kennisgewings van jou foon af na ander dienste"</string>
+ <string name="helper_summary_computer" product="tablet" msgid="467996390095403648">"Hierdie diens deel foto\'s, media en kennisgewings van jou foon af na ander dienste"</string>
<string name="profile_name_generic" msgid="6851028682723034988">"toestel"</string>
<string name="summary_generic" msgid="2346762210105903720"></string>
<string name="consent_yes" msgid="8344487259618762872">"Laat toe"</string>
<string name="consent_no" msgid="2640796915611404382">"Moenie toelaat nie"</string>
+ <string name="consent_ok" msgid="3662376764371001106">"OK"</string>
<string name="permission_sync_confirmation_title" msgid="667074294393493186">"Dra programtoestemmings na jou horlosie toe oor"</string>
<string name="permission_sync_summary" msgid="8873391306499120778">"Om dit makliker te maak om jou horlosie op te stel, sal programme wat gedurende opstelling op jou horlosie geïnstalleer word, dieselfde toestemmings as jou foon gebruik.\n\n Hierdie toestemmings kan toegang tot jou horlosie se mikrofoon en ligging insluit."</string>
</resources>
diff --git a/packages/CompanionDeviceManager/res/values-am/strings.xml b/packages/CompanionDeviceManager/res/values-am/strings.xml
index 5cb306f..0411f3a 100644
--- a/packages/CompanionDeviceManager/res/values-am/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-am/strings.xml
@@ -22,18 +22,30 @@
<string name="chooser_title" msgid="2262294130493605839">"በ<strong><xliff:g id="APP_NAME">%2$s</xliff:g></strong> የሚተዳደር <xliff:g id="PROFILE_NAME">%1$s</xliff:g> ይምረጡ"</string>
<string name="summary_watch" product="default" msgid="7113724443198337683">"<xliff:g id="APP_NAME">%1$s</xliff:g> ከማሳወቂያዎችዎ ጋር መስተጋብር እንዲፈጥር እና የእርስዎን ስልክ፣ ኤስኤምኤስ፣ እውቂያዎች እና የቀን መቁጠሪያ ፈቃዶች እንዲደርስ ይፈቀድለታል።"</string>
<string name="summary_watch" product="tablet" msgid="7113724443198337683">"<xliff:g id="APP_NAME">%1$s</xliff:g> ከማሳወቂያዎችዎ ጋር መስተጋብር እንዲፈጥር እና የእርስዎን ስልክ፣ ኤስኤምኤስ፣ እውቂያዎች እና የቀን መቁጠሪያ ፈቃዶች እንዲደርስ ይፈቀድለታል።"</string>
- <string name="title_app_streaming" msgid="4459136600249308574">"<strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> መተግበሪያዎችን እንዲለቅቅ ይፈቀድለት?"</string>
+ <string name="permission_apps" msgid="6142133265286656158">"መተግበሪያዎች"</string>
+ <string name="permission_apps_summary" msgid="798718816711515431">"የስልክዎን መተግበሪያዎች በዥረት ይልቀቁ"</string>
+ <string name="title_app_streaming" msgid="2270331024626446950">"<strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> ይህን መረጃ ከስልክዎ እንዲደርስበት ይፍቀዱለት"</string>
<string name="summary_app_streaming" product="default" msgid="6105916810614498138">"<strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> ሲገናኙ በዚህ ስልክ ላይ የተጫኑ መተግበሪያዎችን እንዲደርስ ለ<strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong> የርቀት መዳረሻ እንዲያቀርብ ይፍቀዱለት።"</string>
<string name="summary_app_streaming" product="tablet" msgid="2996373715966272792">"<strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> ሲገናኙ በዚህ ጡባዊ ላይ የተጫኑ መተግበሪያዎችን እንዲደርስ ለ<strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong> የርቀት መዳረሻ እንዲያቀርብ ይፍቀዱለት።"</string>
<string name="summary_app_streaming" product="device" msgid="7614171699434639963">"<strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> ሲገናኙ በዚህ መሳሪያ ላይ የተጫኑ መተግበሪያዎችን እንዲደርስ ለ<strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong> የርቀት መዳረሻ እንዲያቀርብ ይፍቀዱለት።"</string>
+ <string name="helper_title_app_streaming" msgid="4151687003439969765">"መሣሪያ ተሻጋሪ አገልግሎቶች"</string>
+ <string name="helper_summary_app_streaming" msgid="5344341720432827388">"ይህ አገልግሎት በእርስዎ መሣሪያዎች መካከል መተግበሪያዎችን ለመልቀቅ ስራ ላይ ይውላል"</string>
<string name="title_automotive_projection" msgid="3296005598978412847"></string>
<string name="summary_automotive_projection" msgid="8683801274662496164"></string>
<string name="title_computer" msgid="4693714143506569253">"<strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> ይህን መረጃ ከስልክዎ ላይ እንዲደርስ ይፍቀዱለት"</string>
<string name="summary_computer" msgid="3798467601598297062"></string>
+ <string name="permission_notification" msgid="693762568127741203">"ማሳወቂያዎች"</string>
+ <string name="permission_notification_summary" msgid="4398672775023193663">"እንደ ውሎች፣ መልዕክቶች እና ፎቶዎች ያሉ መረጃዎችን ጨምሮ ሁሉንም ማሳወቂያዎች ማንበብ ይችላል"</string>
+ <string name="permission_storage" msgid="6831099350839392343">"ፎቶዎች እና ሚዲያ"</string>
+ <string name="permission_storage_summary" msgid="3918240895519506417"></string>
+ <string name="helper_title_computer" msgid="4671071173916176037">"የGoogle Play አገልግሎቶች"</string>
+ <string name="helper_summary_computer" product="default" msgid="467996390095403648">"ይህ አገልግሎት ፎቶዎችን፣ ሚዲያዎችን እና ማሳወቂያዎችን ከስልክዎ ለሌሎች መሣሪያዎች ያጋራል"</string>
+ <string name="helper_summary_computer" product="tablet" msgid="467996390095403648">"ይህ አገልግሎት ፎቶዎችን፣ ሚዲያዎችን እና ማሳወቂያዎችን ከስልክዎ ለሌሎች መሣሪያዎች ያጋራል"</string>
<string name="profile_name_generic" msgid="6851028682723034988">"መሣሪያ"</string>
<string name="summary_generic" msgid="2346762210105903720"></string>
<string name="consent_yes" msgid="8344487259618762872">"ፍቀድ"</string>
<string name="consent_no" msgid="2640796915611404382">"አትፍቀድ"</string>
+ <string name="consent_ok" msgid="3662376764371001106">"እሺ"</string>
<string name="permission_sync_confirmation_title" msgid="667074294393493186">"የመተግበሪያ ፈቃዶችን ወደ የእጅ ሰዓትዎ ያስተላልፉ"</string>
<string name="permission_sync_summary" msgid="8873391306499120778">"የእጅ ሰዓትዎን ማቀናበርን ለማቅለል በማዋቀር ጊዜ በእጅ ሰዓትዎ ላይ የተጫኑ መተግበሪያዎች እንደ ስልክዎ ተመሳሳይ ፈቃዶችን ይጠቀማሉ።\n\n እነዚህ ፈቃዶች የእጅ ሰዓትዎ ማይክሮፎን እና አካባቢ መዳረሻን ሊያካትቱ ይችላሉ።"</string>
</resources>
diff --git a/packages/CompanionDeviceManager/res/values-ar/strings.xml b/packages/CompanionDeviceManager/res/values-ar/strings.xml
index b4c74ad..5c00999 100644
--- a/packages/CompanionDeviceManager/res/values-ar/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-ar/strings.xml
@@ -22,18 +22,30 @@
<string name="chooser_title" msgid="2262294130493605839">"اختَر <xliff:g id="PROFILE_NAME">%1$s</xliff:g> ليديره تطبيق <strong><xliff:g id="APP_NAME">%2$s</xliff:g></strong>"</string>
<string name="summary_watch" product="default" msgid="7113724443198337683">"سيتم السماح لتطبيق <xliff:g id="APP_NAME">%1$s</xliff:g> بالتفاعل مع الإشعارات والوصول إلى أذونات الهاتف والرسائل القصيرة وجهات الاتصال والتقويم."</string>
<string name="summary_watch" product="tablet" msgid="7113724443198337683">"سيتم السماح لتطبيق <xliff:g id="APP_NAME">%1$s</xliff:g> بالتفاعل مع الإشعارات والوصول إلى أذونات الهاتف والرسائل القصيرة وجهات الاتصال والتقويم."</string>
- <string name="title_app_streaming" msgid="4459136600249308574">"هل تريد السماح لتطبيق <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> ببث التطبيقات؟"</string>
+ <string name="permission_apps" msgid="6142133265286656158">"التطبيقات"</string>
+ <string name="permission_apps_summary" msgid="798718816711515431">"بث تطبيقات هاتفك"</string>
+ <string name="title_app_streaming" msgid="2270331024626446950">"السماح لتطبيق <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> بالوصول إلى هذه المعلومات من هاتفك"</string>
<string name="summary_app_streaming" product="default" msgid="6105916810614498138">"السماح لتطبيق <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> بمنح الإذن بالوصول عن بُعد إلى التطبيقات المثبَّتة <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong> الإذن بالوصول عن بُعد إلى التطبيقات المثبَّتة على هذا الهاتف عندما يكون متصلاً بالإنترنت."</string>
<string name="summary_app_streaming" product="tablet" msgid="2996373715966272792">"السماح لتطبيق <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> بمنح <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong> الإذن بالوصول عن بُعد إلى التطبيقات المثبَّتة على هذا الجهاز اللوحي عندما يكون متصلاً بالإنترنت."</string>
<string name="summary_app_streaming" product="device" msgid="7614171699434639963">"السماح لتطبيق <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> بمنح <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong> الإذن بالوصول عن بُعد إلى التطبيقات المثبَّتة على هذا الجهاز عندما يكون متصلاً بالإنترنت."</string>
+ <string name="helper_title_app_streaming" msgid="4151687003439969765">"الخدمات التي تعمل بين الأجهزة"</string>
+ <string name="helper_summary_app_streaming" msgid="5344341720432827388">"تُستخدَم هذه الخدمة لبث التطبيقات بين الأجهزة."</string>
<string name="title_automotive_projection" msgid="3296005598978412847"></string>
<string name="summary_automotive_projection" msgid="8683801274662496164"></string>
<string name="title_computer" msgid="4693714143506569253">"السماح لتطبيق <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> بالوصول إلى هذه المعلومات من هاتفك"</string>
<string name="summary_computer" msgid="3798467601598297062"></string>
+ <string name="permission_notification" msgid="693762568127741203">"الإشعارات"</string>
+ <string name="permission_notification_summary" msgid="4398672775023193663">"يمكن لهذا الملف الشخصي قراءة جميع الإشعارات، بما في ذلك المعلومات، مثل جهات الاتصال والرسائل والصور."</string>
+ <string name="permission_storage" msgid="6831099350839392343">"الصور والوسائط"</string>
+ <string name="permission_storage_summary" msgid="3918240895519506417"></string>
+ <string name="helper_title_computer" msgid="4671071173916176037">"خدمات Google Play"</string>
+ <string name="helper_summary_computer" product="default" msgid="467996390095403648">"تشارك هذه الخدمة الصور والوسائط والإشعارات من هاتفك إلى أجهزة أخرى."</string>
+ <string name="helper_summary_computer" product="tablet" msgid="467996390095403648">"تشارك هذه الخدمة الصور والوسائط والإشعارات من هاتفك إلى أجهزة أخرى."</string>
<string name="profile_name_generic" msgid="6851028682723034988">"جهاز"</string>
<string name="summary_generic" msgid="2346762210105903720"></string>
<string name="consent_yes" msgid="8344487259618762872">"السماح"</string>
<string name="consent_no" msgid="2640796915611404382">"عدم السماح"</string>
+ <string name="consent_ok" msgid="3662376764371001106">"حسنًا"</string>
<string name="permission_sync_confirmation_title" msgid="667074294393493186">"نقل أذونات التطبيقات إلى ساعتك"</string>
<string name="permission_sync_summary" msgid="8873391306499120778">"لتسهيل إعداد ساعتك، فإن التطبيقات التي يتم تثبيتها على ساعتك أثناء الإعداد ستستخدم الأذونات نفسها التي يستخدمها هاتفك.\n\n قد تشتمل هذه الأذونات على الوصول إلى ميكروفون ساعتك وبيانات موقعها الجغرافي."</string>
</resources>
diff --git a/packages/CompanionDeviceManager/res/values-as/strings.xml b/packages/CompanionDeviceManager/res/values-as/strings.xml
index b2865dc..dbb5c3b 100644
--- a/packages/CompanionDeviceManager/res/values-as/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-as/strings.xml
@@ -22,18 +22,30 @@
<string name="chooser_title" msgid="2262294130493605839">"<strong><xliff:g id="APP_NAME">%2$s</xliff:g></strong>এ পৰিচালনা কৰিব লগা এটা <xliff:g id="PROFILE_NAME">%1$s</xliff:g> বাছনি কৰক"</string>
<string name="summary_watch" product="default" msgid="7113724443198337683">"<xliff:g id="APP_NAME">%1$s</xliff:g>ক আপোনাৰ জাননী ব্যৱহাৰ কৰিবলৈ আৰু আপোনাৰ ফ’ন, এছএমএছ, সম্পৰ্ক আৰু কেলেণ্ডাৰৰ অনুমতি এক্সেছ কৰিবলৈ দিয়া হ’ব।"</string>
<string name="summary_watch" product="tablet" msgid="7113724443198337683">"<xliff:g id="APP_NAME">%1$s</xliff:g>ক আপোনাৰ জাননী ব্যৱহাৰ কৰিবলৈ আৰু আপোনাৰ ফ’ন, এছএমএছ, সম্পৰ্ক আৰু কেলেণ্ডাৰৰ অনুমতি এক্সেছ কৰিবলৈ দিয়া হ’ব।"</string>
- <string name="title_app_streaming" msgid="4459136600249308574">"<strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong>ক এপ্লিকেশ্বন ষ্ট্ৰীম কৰিবলৈ অনুমতি দিবনে?"</string>
+ <string name="permission_apps" msgid="6142133265286656158">"এপ্"</string>
+ <string name="permission_apps_summary" msgid="798718816711515431">"আপোনাৰ ফ’নৰ এপ্ ষ্ট্ৰীম কৰক"</string>
+ <string name="title_app_streaming" msgid="2270331024626446950">"<strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong>ক আপোনাৰ ফ’নৰ পৰা এই তথ্যখিনি এক্সেছ কৰাৰ অনুমতি দিয়ক"</string>
<string name="summary_app_streaming" product="default" msgid="6105916810614498138">"সংযোগ কৰিলে <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong>ক এই ফ’নটোত ইনষ্টল কৰি থোৱা এপ্লিকেশ্বনসমূহ এক্সেছ কৰিবলৈ <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong>ক ৰিম’ট এক্সেছ দিবলৈ দিয়ক।"</string>
<string name="summary_app_streaming" product="tablet" msgid="2996373715966272792">"সংযোগ কৰিলে <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong>ক এই টেবলেটটোত ইনষ্টল কৰি থোৱা এপ্লিকেশ্বনসমূহ এক্সেছ কৰিবলৈ <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong>ক ৰিম’ট এক্সেছ দিবলৈ দিয়ক।"</string>
<string name="summary_app_streaming" product="device" msgid="7614171699434639963">"সংযোগ কৰিলে <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong>ক এই ডিভাইচটোত ইনষ্টল কৰি থোৱা এপ্লিকেশ্বনসমূহ এক্সেছ কৰিবলৈ <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong>ক ৰিম’ট এক্সেছ দিবলৈ দিয়ক।"</string>
+ <string name="helper_title_app_streaming" msgid="4151687003439969765">"ক্ৰছ-ডিভাইচ সেৱাসমূহ"</string>
+ <string name="helper_summary_app_streaming" msgid="5344341720432827388">"এই সেৱাটো আপোনাৰ ডিভাইচবোৰৰ মাজত এপ্ ষ্ট্ৰীম কৰিবলৈ ব্যৱহাৰ কৰা হয়"</string>
<string name="title_automotive_projection" msgid="3296005598978412847"></string>
<string name="summary_automotive_projection" msgid="8683801274662496164"></string>
<string name="title_computer" msgid="4693714143506569253">"<strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong>ক আপোনাৰ ফ’নৰ পৰা এই তথ্যখিনি এক্সেছ কৰাৰ অনুমতি দিয়ক"</string>
<string name="summary_computer" msgid="3798467601598297062"></string>
+ <string name="permission_notification" msgid="693762568127741203">"জাননী"</string>
+ <string name="permission_notification_summary" msgid="4398672775023193663">"চুক্তি, বাৰ্তা আৰু ফট’ৰ দৰে তথ্যকে ধৰি আটাইবোৰ জাননী পঢ়িব পাৰে"</string>
+ <string name="permission_storage" msgid="6831099350839392343">"ফট’ আৰু মিডিয়া"</string>
+ <string name="permission_storage_summary" msgid="3918240895519506417"></string>
+ <string name="helper_title_computer" msgid="4671071173916176037">"Google Play সেৱা"</string>
+ <string name="helper_summary_computer" product="default" msgid="467996390095403648">"এই সেৱাটোৱে আপোনাৰ ফ\'নৰ পৰা অন্য ডিভাইচলৈ ফট’, মিডিয়া আৰু জাননী শ্বেয়াৰ কৰে"</string>
+ <string name="helper_summary_computer" product="tablet" msgid="467996390095403648">"এই সেৱাটোৱে আপোনাৰ ফ\'নৰ পৰা অন্য ডিভাইচলৈ ফট’, মিডিয়া আৰু জাননী শ্বেয়াৰ কৰে"</string>
<string name="profile_name_generic" msgid="6851028682723034988">"ডিভাইচ"</string>
<string name="summary_generic" msgid="2346762210105903720"></string>
<string name="consent_yes" msgid="8344487259618762872">"অনুমতি দিয়ক"</string>
<string name="consent_no" msgid="2640796915611404382">"অনুমতি নিদিব"</string>
+ <string name="consent_ok" msgid="3662376764371001106">"ঠিক আছে"</string>
<string name="permission_sync_confirmation_title" msgid="667074294393493186">"আপোনাৰ ঘড়ীলৈ এপৰ অনুমতিসমূহ স্থানান্তৰ কৰক"</string>
<string name="permission_sync_summary" msgid="8873391306499120778">"আপোনাৰ ঘড়ীটো ছেটআপ কৰাটো অধিক সহজ কৰি তুলিবলৈ, এয়া কৰাৰ সময়ত আপোনাৰ ঘড়ীটোত ইনষ্টল কৰি থোৱা এপ্সমূহে আপোনাৰ ফ’নৰ দৰে একেই অনুমতিসমূহ ব্যৱহাৰ কৰিব।\n\n এই অনুমতিসমূহত আপোনাৰ ঘড়ীৰ মাইক্ৰ’ফ’ন আৰু অৱস্থানৰ এক্সেছ অন্তৰ্ভুক্ত হ’ব পাৰে।"</string>
</resources>
diff --git a/packages/CompanionDeviceManager/res/values-az/strings.xml b/packages/CompanionDeviceManager/res/values-az/strings.xml
index e8e4e76..a0b5b8c 100644
--- a/packages/CompanionDeviceManager/res/values-az/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-az/strings.xml
@@ -22,18 +22,30 @@
<string name="chooser_title" msgid="2262294130493605839">"<strong><xliff:g id="APP_NAME">%2$s</xliff:g></strong> tərəfindən idarə ediləcək <xliff:g id="PROFILE_NAME">%1$s</xliff:g> seçin"</string>
<string name="summary_watch" product="default" msgid="7113724443198337683">"<xliff:g id="APP_NAME">%1$s</xliff:g> bildirişlərinizə, Telefon, SMS, Kontaktlar və Təqvimə giriş əldə edəcək."</string>
<string name="summary_watch" product="tablet" msgid="7113724443198337683">"<xliff:g id="APP_NAME">%1$s</xliff:g> bildirişlərinizə, Telefon, SMS, Kontaktlar və Təqvimə giriş əldə edəcək."</string>
- <string name="title_app_streaming" msgid="4459136600249308574">"<strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> tətbiqinin tətbiqlərdə yayım etməsinə icazə verilsin?"</string>
+ <string name="permission_apps" msgid="6142133265286656158">"Tətbiqlər"</string>
+ <string name="permission_apps_summary" msgid="798718816711515431">"Telefonunuzun tətbiqlərini yayımlayın"</string>
+ <string name="title_app_streaming" msgid="2270331024626446950">"<strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> tətbiqinə telefonunuzdan bu məlumata giriş icazəsi verin"</string>
<string name="summary_app_streaming" product="default" msgid="6105916810614498138">"<strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> tətbiqinə <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong> cihazının qoşulduqda bu telefonda quraşdırılmış tətbiqlərə uzaqdan giriş icazəsi verməsinə imkan verin."</string>
<string name="summary_app_streaming" product="tablet" msgid="2996373715966272792">"<strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> tətbiqinə <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong> cihazının qoşulduqda bu planşetdə quraşdırılmış tətbiqlərə uzaqdan giriş icazəsi verməsinə imkan verin."</string>
<string name="summary_app_streaming" product="device" msgid="7614171699434639963">"<strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> tətbiqinə <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong> cihazının qoşulduqda bu cihazda quraşdırılmış tətbiqlərə uzaqdan giriş icazəsi verməsinə imkan verin."</string>
+ <string name="helper_title_app_streaming" msgid="4151687003439969765">"Cihazlararası xidmətlər"</string>
+ <string name="helper_summary_app_streaming" msgid="5344341720432827388">"Bu xidmət cihazlarınız arasında tətbiqləri yayımlamaq üçün istifadə olunur"</string>
<string name="title_automotive_projection" msgid="3296005598978412847"></string>
<string name="summary_automotive_projection" msgid="8683801274662496164"></string>
<string name="title_computer" msgid="4693714143506569253">"<strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> tətbiqinə telefonunuzdan bu məlumata giriş icazəsi verin"</string>
<string name="summary_computer" msgid="3798467601598297062"></string>
+ <string name="permission_notification" msgid="693762568127741203">"Bildirişlər"</string>
+ <string name="permission_notification_summary" msgid="4398672775023193663">"Bütün bildirişləri, o cümlədən müqavilələr, mesajlar və fotolar kimi məlumatları oxuya bilər"</string>
+ <string name="permission_storage" msgid="6831099350839392343">"Foto və media"</string>
+ <string name="permission_storage_summary" msgid="3918240895519506417"></string>
+ <string name="helper_title_computer" msgid="4671071173916176037">"Google Play xidmətləri"</string>
+ <string name="helper_summary_computer" product="default" msgid="467996390095403648">"Bu xidmət telefonunuzdakı foto, media və bildirişləri digər cihazlarla paylaşır"</string>
+ <string name="helper_summary_computer" product="tablet" msgid="467996390095403648">"Bu xidmət telefonunuzdakı foto, media və bildirişləri digər cihazlarla paylaşır"</string>
<string name="profile_name_generic" msgid="6851028682723034988">"cihaz"</string>
<string name="summary_generic" msgid="2346762210105903720"></string>
<string name="consent_yes" msgid="8344487259618762872">"İcazə verin"</string>
<string name="consent_no" msgid="2640796915611404382">"İcazə verməyin"</string>
+ <string name="consent_ok" msgid="3662376764371001106">"OK"</string>
<string name="permission_sync_confirmation_title" msgid="667074294393493186">"Tətbiq icazələrini saatınıza köçürün"</string>
<string name="permission_sync_summary" msgid="8873391306499120778">"Saatınızı ayarlamağı asanlaşdırmaq üçün ayarlama zamanı saatınızda quraşdırılmış tətbiqlər telefonunuzla eyni icazələrdən istifadə edəcək.\n\n Bu icazələrə saatınızın mikrofonuna və məkanına giriş daxil ola bilər."</string>
</resources>
diff --git a/packages/CompanionDeviceManager/res/values-b+sr+Latn/strings.xml b/packages/CompanionDeviceManager/res/values-b+sr+Latn/strings.xml
index 5d98a13..78cac0a 100644
--- a/packages/CompanionDeviceManager/res/values-b+sr+Latn/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-b+sr+Latn/strings.xml
@@ -22,18 +22,30 @@
<string name="chooser_title" msgid="2262294130493605839">"Odaberite profil <xliff:g id="PROFILE_NAME">%1$s</xliff:g> kojim će upravljati aplikacija <strong><xliff:g id="APP_NAME">%2$s</xliff:g></strong>"</string>
<string name="summary_watch" product="default" msgid="7113724443198337683">"<xliff:g id="APP_NAME">%1$s</xliff:g> će dobiti dozvolu za interakciju sa obaveštenjima i pristup dozvolama za telefon, SMS poruke, kontakte i kalendar."</string>
<string name="summary_watch" product="tablet" msgid="7113724443198337683">"<xliff:g id="APP_NAME">%1$s</xliff:g> će dobiti dozvolu za interakciju sa obaveštenjima i pristup dozvolama za telefon, SMS poruke, kontakte i kalendar."</string>
- <string name="title_app_streaming" msgid="4459136600249308574">"Želite da dozvolite aplikaciji <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> da strimuje aplikacije?"</string>
+ <string name="permission_apps" msgid="6142133265286656158">"Aplikacije"</string>
+ <string name="permission_apps_summary" msgid="798718816711515431">"Strimujte aplikacije na telefonu"</string>
+ <string name="title_app_streaming" msgid="2270331024626446950">"Dozvolite da <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> pristupa ovim informacijama sa telefona"</string>
<string name="summary_app_streaming" product="default" msgid="6105916810614498138">"Dozvolite aplikaciji <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> da daljinski pristupa aplikacijama instaliranim na telefonu <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong> kada je povezan."</string>
<string name="summary_app_streaming" product="tablet" msgid="2996373715966272792">"Dozvolite aplikaciji <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> da daljinski pristupa aplikacijama instaliranim na tabletu <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong> kada je povezan."</string>
<string name="summary_app_streaming" product="device" msgid="7614171699434639963">"Dozvolite aplikaciji <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> da daljinski pristupa aplikacijama instaliranim na uređaju <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong> kada je povezan."</string>
+ <string name="helper_title_app_streaming" msgid="4151687003439969765">"Usluge na više uređaja"</string>
+ <string name="helper_summary_app_streaming" msgid="5344341720432827388">"Ova usluga se koristi za strimovanje aplikacija između uređaja"</string>
<string name="title_automotive_projection" msgid="3296005598978412847"></string>
<string name="summary_automotive_projection" msgid="8683801274662496164"></string>
<string name="title_computer" msgid="4693714143506569253">"Dozvolite da <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> pristupa ovim informacijama sa telefona"</string>
<string name="summary_computer" msgid="3798467601598297062"></string>
+ <string name="permission_notification" msgid="693762568127741203">"Obaveštenja"</string>
+ <string name="permission_notification_summary" msgid="4398672775023193663">"Može da čita sva obaveštenja, uključujući informacije poput ugovora, poruka i slika"</string>
+ <string name="permission_storage" msgid="6831099350839392343">"Slike i mediji"</string>
+ <string name="permission_storage_summary" msgid="3918240895519506417"></string>
+ <string name="helper_title_computer" msgid="4671071173916176037">"Google Play usluge"</string>
+ <string name="helper_summary_computer" product="default" msgid="467996390095403648">"Ova usluga deli slike, medijski sadržaj i obaveštenja sa telefona na druge uređaje"</string>
+ <string name="helper_summary_computer" product="tablet" msgid="467996390095403648">"Ova usluga deli slike, medijski sadržaj i obaveštenja sa telefona na druge uređaje"</string>
<string name="profile_name_generic" msgid="6851028682723034988">"uređaj"</string>
<string name="summary_generic" msgid="2346762210105903720"></string>
<string name="consent_yes" msgid="8344487259618762872">"Dozvoli"</string>
<string name="consent_no" msgid="2640796915611404382">"Ne dozvoli"</string>
+ <string name="consent_ok" msgid="3662376764371001106">"Potvrdi"</string>
<string name="permission_sync_confirmation_title" msgid="667074294393493186">"Prenesite dozvole za aplikacije na sat"</string>
<string name="permission_sync_summary" msgid="8873391306499120778">"Da bismo pojednostavili podešavanje sata, aplikacije instalirane na satu tokom podešavanja će koristiti iste dozvole kao telefon.\n\n Te dozvole mogu da obuhvataju pristup mikrofonu i lokaciji sata."</string>
</resources>
diff --git a/packages/CompanionDeviceManager/res/values-be/strings.xml b/packages/CompanionDeviceManager/res/values-be/strings.xml
index 3a57bcc..ed521b1 100644
--- a/packages/CompanionDeviceManager/res/values-be/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-be/strings.xml
@@ -22,18 +22,30 @@
<string name="chooser_title" msgid="2262294130493605839">"Выберыце прыладу (<xliff:g id="PROFILE_NAME">%1$s</xliff:g>), якой будзе кіраваць праграма <strong><xliff:g id="APP_NAME">%2$s</xliff:g></strong>"</string>
<string name="summary_watch" product="default" msgid="7113724443198337683">"<xliff:g id="APP_NAME">%1$s</xliff:g> атрымае доступ да вашых апавяшчэнняў, тэлефона, SMS, кантактаў і календара."</string>
<string name="summary_watch" product="tablet" msgid="7113724443198337683">"<xliff:g id="APP_NAME">%1$s</xliff:g> атрымае доступ да вашых апавяшчэнняў, тэлефона, SMS, кантактаў і календара."</string>
- <string name="title_app_streaming" msgid="4459136600249308574">"Дазволіць праграме <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> перадаваць праграмы плынню?"</string>
+ <string name="permission_apps" msgid="6142133265286656158">"Праграмы"</string>
+ <string name="permission_apps_summary" msgid="798718816711515431">"Трансліруйце змесціва праграм з вашага тэлефона"</string>
+ <string name="title_app_streaming" msgid="2270331024626446950">"Дазвольце праграме <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> мець доступ да гэтай інфармацыі з вашага тэлефона"</string>
<string name="summary_app_streaming" product="default" msgid="6105916810614498138">"Дазвольце праграме <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> атрымліваць аддалены доступ да праграм, усталяваных на тэлефоне <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong> (калі тэлефон падключаны)."</string>
<string name="summary_app_streaming" product="tablet" msgid="2996373715966272792">"Дазвольце праграме <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> атрымліваць аддалены доступ да праграм, усталяваных на планшэце <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong> (калі планшэт падключаны)."</string>
<string name="summary_app_streaming" product="device" msgid="7614171699434639963">"Дазвольце праграме <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> атрымліваць аддалены доступ да праграм, усталяваных на прыладзе <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong> (калі прылада падключана)."</string>
+ <string name="helper_title_app_streaming" msgid="4151687003439969765">"Сэрвісы для некалькіх прылад"</string>
+ <string name="helper_summary_app_streaming" msgid="5344341720432827388">"Гэты сэрвіс выкарыстоўваецца для перадачы праграм плынню паміж прыладамі"</string>
<string name="title_automotive_projection" msgid="3296005598978412847"></string>
<string name="summary_automotive_projection" msgid="8683801274662496164"></string>
<string name="title_computer" msgid="4693714143506569253">"Дазвольце праграме <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> мець доступ да гэтай інфармацыі з вашага тэлефона"</string>
<string name="summary_computer" msgid="3798467601598297062"></string>
+ <string name="permission_notification" msgid="693762568127741203">"Апавяшчэнні"</string>
+ <string name="permission_notification_summary" msgid="4398672775023193663">"Можа счытваць усе апавяшчэнні, уключаючы паведамленні, фота і інфармацыю пра кантакты"</string>
+ <string name="permission_storage" msgid="6831099350839392343">"Фота і медыяфайлы"</string>
+ <string name="permission_storage_summary" msgid="3918240895519506417"></string>
+ <string name="helper_title_computer" msgid="4671071173916176037">"Сэрвісы Google Play"</string>
+ <string name="helper_summary_computer" product="default" msgid="467996390095403648">"Гэты сэрвіс абагульвае з іншымі прыладамі фота, медыяфайлы і апавяшчэнні, якія захоўваюцца на вашым тэлефоне"</string>
+ <string name="helper_summary_computer" product="tablet" msgid="467996390095403648">"Гэты сэрвіс абагульвае з іншымі прыладамі фота, медыяфайлы і апавяшчэнні, якія захоўваюцца на вашым тэлефоне"</string>
<string name="profile_name_generic" msgid="6851028682723034988">"прылада"</string>
<string name="summary_generic" msgid="2346762210105903720"></string>
<string name="consent_yes" msgid="8344487259618762872">"Дазволіць"</string>
<string name="consent_no" msgid="2640796915611404382">"Не дазваляць"</string>
+ <string name="consent_ok" msgid="3662376764371001106">"ОК"</string>
<string name="permission_sync_confirmation_title" msgid="667074294393493186">"Перанос дазволаў праграм на ваш гадзіннік"</string>
<string name="permission_sync_summary" msgid="8873391306499120778">"Для праграм, усталяваных на гадзіннік падчас наладжвання, будуць дзейнічаць тыя самыя дазволы, што і на тэлефоне.\n\n Так гадзіннік можа атрымаць доступ да мікрафона і даных пра месцазнаходжанне."</string>
</resources>
diff --git a/packages/CompanionDeviceManager/res/values-bg/strings.xml b/packages/CompanionDeviceManager/res/values-bg/strings.xml
index d29a908..fe65bda4 100644
--- a/packages/CompanionDeviceManager/res/values-bg/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-bg/strings.xml
@@ -22,18 +22,30 @@
<string name="chooser_title" msgid="2262294130493605839">"Изберете устройство (<xliff:g id="PROFILE_NAME">%1$s</xliff:g>), което да се управлява от <strong><xliff:g id="APP_NAME">%2$s</xliff:g></strong>"</string>
<string name="summary_watch" product="default" msgid="7113724443198337683">"<xliff:g id="APP_NAME">%1$s</xliff:g> ще получи разрешение да взаимодейства с известията ви и да осъществява достъп до разрешенията за телефона, SMS съобщенията, контактите и календара."</string>
<string name="summary_watch" product="tablet" msgid="7113724443198337683">"<xliff:g id="APP_NAME">%1$s</xliff:g> ще получи разрешение да взаимодейства с известията ви и да осъществява достъп до разрешенията за телефона, SMS съобщенията, контактите и календара."</string>
- <string name="title_app_streaming" msgid="4459136600249308574">"Разрешавате ли на <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> да предава поточно приложения?"</string>
+ <string name="permission_apps" msgid="6142133265286656158">"Приложения"</string>
+ <string name="permission_apps_summary" msgid="798718816711515431">"Поточно предаване на приложенията на телефона ви"</string>
+ <string name="title_app_streaming" msgid="2270331024626446950">"Разрешете на <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> да осъществява достъп до тази информация от телефона ви"</string>
<string name="summary_app_streaming" product="default" msgid="6105916810614498138">"Разрешете на <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> да предоставя на <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong> отдалечен достъп до приложенията, инсталирани на този телефон, когато има установена връзка."</string>
<string name="summary_app_streaming" product="tablet" msgid="2996373715966272792">"Разрешете на <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> да предоставя на <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong> отдалечен достъп до приложенията, инсталирани на този таблет, когато има установена връзка."</string>
<string name="summary_app_streaming" product="device" msgid="7614171699434639963">"Разрешете на <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> да предоставя на <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong> отдалечен достъп до приложенията, инсталирани на това устройство, когато има установена връзка."</string>
+ <string name="helper_title_app_streaming" msgid="4151687003439969765">"Услуги за различни устройства"</string>
+ <string name="helper_summary_app_streaming" msgid="5344341720432827388">"Тази услуга служи за поточно предаване на приложения между устройствата ви"</string>
<string name="title_automotive_projection" msgid="3296005598978412847"></string>
<string name="summary_automotive_projection" msgid="8683801274662496164"></string>
<string name="title_computer" msgid="4693714143506569253">"Разрешете на <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> да осъществява достъп до тази информация от телефона ви"</string>
<string name="summary_computer" msgid="3798467601598297062"></string>
+ <string name="permission_notification" msgid="693762568127741203">"Известия"</string>
+ <string name="permission_notification_summary" msgid="4398672775023193663">"Може да чете всички известия, включително различна информация, като например договори, съобщения и снимки"</string>
+ <string name="permission_storage" msgid="6831099350839392343">"Снимки и мултимедия"</string>
+ <string name="permission_storage_summary" msgid="3918240895519506417"></string>
+ <string name="helper_title_computer" msgid="4671071173916176037">"Услуги за Google Play"</string>
+ <string name="helper_summary_computer" product="default" msgid="467996390095403648">"Тази услуга споделя с други устройства снимки, мултимедия и известия от телефона ви"</string>
+ <string name="helper_summary_computer" product="tablet" msgid="467996390095403648">"Тази услуга споделя с други устройства снимки, мултимедия и известия от телефона ви"</string>
<string name="profile_name_generic" msgid="6851028682723034988">"устройство"</string>
<string name="summary_generic" msgid="2346762210105903720"></string>
<string name="consent_yes" msgid="8344487259618762872">"Разрешаване"</string>
<string name="consent_no" msgid="2640796915611404382">"Забраняване"</string>
+ <string name="consent_ok" msgid="3662376764371001106">"OK"</string>
<string name="permission_sync_confirmation_title" msgid="667074294393493186">"Прехвърляне на разрешенията за приложенията към часовника"</string>
<string name="permission_sync_summary" msgid="8873391306499120778">"За по-лесно конфигуриране на часовника ви приложенията, инсталирани на него по време на настройването, ще използват същите разрешения като предоставените на телефона ви.\n\nТе може да включват достъп до микрофона и местоположението на часовника ви."</string>
</resources>
diff --git a/packages/CompanionDeviceManager/res/values-bn/strings.xml b/packages/CompanionDeviceManager/res/values-bn/strings.xml
index 7d0b097..58c6c26 100644
--- a/packages/CompanionDeviceManager/res/values-bn/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-bn/strings.xml
@@ -22,18 +22,30 @@
<string name="chooser_title" msgid="2262294130493605839">"<xliff:g id="PROFILE_NAME">%1$s</xliff:g> বেছে নিন যেটি <strong><xliff:g id="APP_NAME">%2$s</xliff:g></strong> ম্যানেজ করবে"</string>
<string name="summary_watch" product="default" msgid="7113724443198337683">"<xliff:g id="APP_NAME">%1$s</xliff:g> আপনার বিজ্ঞপ্তির সাথে ইন্টার্যাক্ট করতে পারবে, তার সাথে আপনার ফোন, এমএসএস, পরিচিতি এবং ক্যালেন্ডারের অনুমতিও অ্যাক্সেস করতে পারবে।"</string>
<string name="summary_watch" product="tablet" msgid="7113724443198337683">"<xliff:g id="APP_NAME">%1$s</xliff:g> আপনার বিজ্ঞপ্তির সাথে ইন্টার্যাক্ট করতে পারবে, তার সাথে আপনার ফোন, এমএসএস, পরিচিতি এবং ক্যালেন্ডারের অনুমতিও অ্যাক্সেস করতে পারবে।"</string>
- <string name="title_app_streaming" msgid="4459136600249308574">"অ্যাপ্লিকেশন স্ট্রিম করার জন্য <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> কে অনুমতি দেবেন?"</string>
+ <string name="permission_apps" msgid="6142133265286656158">"অ্যাপ"</string>
+ <string name="permission_apps_summary" msgid="798718816711515431">"আপনার ফোনের অ্যাপ স্ট্রিমিংয়ের মাধ্যমে কাস্ট করুন"</string>
+ <string name="title_app_streaming" msgid="2270331024626446950">"আপনার ফোন থেকে <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> অ্যাপকে এই তথ্য অ্যাক্সেস করার অনুমতি দিন"</string>
<string name="summary_app_streaming" product="default" msgid="6105916810614498138">"<strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> কে <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong>এ দূরবর্তী অ্যাক্সেস প্রদান করতে দিন যাতে কানেক্ট থাকাকালীন এই ফোনে ইনস্টল করা অ্যাপ্লিকেশনগুলিতে অ্যাক্সেস করা যায়।"</string>
<string name="summary_app_streaming" product="tablet" msgid="2996373715966272792">"<strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> কে <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong>এ দূরবর্তী অ্যাক্সেস প্রদান করতে দিন যাতে কানেক্ট থাকাকালীন এই ট্যাবলেটে ইনস্টল করা অ্যাপ্লিকেশনগুলিতে অ্যাক্সেস করা যায়।"</string>
<string name="summary_app_streaming" product="device" msgid="7614171699434639963">"<strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> কে <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong>এ দূরবর্তী অ্যাক্সেস প্রদান করতে দিন যাতে কানেক্ট থাকাকালীন এই ডিভাইসে ইনস্টল করা অ্যাপ্লিকেশনগুলিতে অ্যাক্সেস করা যায়।"</string>
+ <string name="helper_title_app_streaming" msgid="4151687003439969765">"ক্রস-ডিভাইস পরিষেবা"</string>
+ <string name="helper_summary_app_streaming" msgid="5344341720432827388">"আপনার ডিভাইসের মধ্যে অ্যাপ স্ট্রিম করার জন্য এই পরিষেবা ব্যবহার করা হয়"</string>
<string name="title_automotive_projection" msgid="3296005598978412847"></string>
<string name="summary_automotive_projection" msgid="8683801274662496164"></string>
<string name="title_computer" msgid="4693714143506569253">"আপনার ফোন থেকে <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong>-কে এই তথ্য অ্যাক্সেস করার অনুমতি দিন"</string>
<string name="summary_computer" msgid="3798467601598297062"></string>
+ <string name="permission_notification" msgid="693762568127741203">"বিজ্ঞপ্তি"</string>
+ <string name="permission_notification_summary" msgid="4398672775023193663">"চুক্তি, মেসেজ ও ফটোর সহ সব বিজ্ঞপ্তি পড়তে পারে"</string>
+ <string name="permission_storage" msgid="6831099350839392343">"ফটো ও মিডিয়া"</string>
+ <string name="permission_storage_summary" msgid="3918240895519506417"></string>
+ <string name="helper_title_computer" msgid="4671071173916176037">"Google Play পরিষেবা"</string>
+ <string name="helper_summary_computer" product="default" msgid="467996390095403648">"এই পরিষেবা আপনার ফোন থেকে অন্যান্য ডিভাইসে ফটো, মিডিয়া ও বিজ্ঞপ্তি শেয়ার করে"</string>
+ <string name="helper_summary_computer" product="tablet" msgid="467996390095403648">"এই পরিষেবা আপনার ফোন থেকে অন্যান্য ডিভাইসে ফটো, মিডিয়া ও বিজ্ঞপ্তি শেয়ার করে"</string>
<string name="profile_name_generic" msgid="6851028682723034988">"ডিভাইস"</string>
<string name="summary_generic" msgid="2346762210105903720"></string>
<string name="consent_yes" msgid="8344487259618762872">"অনুমতি দিন"</string>
<string name="consent_no" msgid="2640796915611404382">"অনুমতি দেবেন না"</string>
+ <string name="consent_ok" msgid="3662376764371001106">"ঠিক আছে"</string>
<string name="permission_sync_confirmation_title" msgid="667074294393493186">"অ্যাপকে দেওয়া অনুমতি আপনার ঘড়িতে ট্রান্সফার করুন"</string>
<string name="permission_sync_summary" msgid="8873391306499120778">"ঘড়ি আরও সহজে সেট আপ করতে, সেট আপ চলাকালীন আপনার ঘড়িতে ইনস্টল করা অ্যাপ ফোনের মতো একই অনুমতি ব্যবহার করবে।\n\n এইসব অনুমতির মধ্যে আপনার ঘড়ির মাইক্রোফোন ও লোকেশন সম্পর্কে তথ্যের অ্যাক্সেস অন্তর্ভুক্ত থাকতে পারে।"</string>
</resources>
diff --git a/packages/CompanionDeviceManager/res/values-bs/strings.xml b/packages/CompanionDeviceManager/res/values-bs/strings.xml
index a723da8..1ce8944 100644
--- a/packages/CompanionDeviceManager/res/values-bs/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-bs/strings.xml
@@ -22,18 +22,30 @@
<string name="chooser_title" msgid="2262294130493605839">"Odaberite uređaj <xliff:g id="PROFILE_NAME">%1$s</xliff:g> kojim će upravljati aplikacija <strong><xliff:g id="APP_NAME">%2$s</xliff:g></strong>"</string>
<string name="summary_watch" product="default" msgid="7113724443198337683">"Aplikaciji <xliff:g id="APP_NAME">%1$s</xliff:g> će se dozvoliti da ostvari interakciju s vašim obavještenjima i da pristupi odobrenjima za Telefon, SMS, Kontakte i Kalendar."</string>
<string name="summary_watch" product="tablet" msgid="7113724443198337683">"Aplikaciji <xliff:g id="APP_NAME">%1$s</xliff:g> će se dozvoliti da ostvari interakciju s vašim obavještenjima i da pristupi odobrenjima za Telefon, SMS, Kontakte i Kalendar."</string>
- <string name="title_app_streaming" msgid="4459136600249308574">"Dozvoliti da <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> prenosi aplikacije?"</string>
+ <string name="permission_apps" msgid="6142133265286656158">"Aplikacije"</string>
+ <string name="permission_apps_summary" msgid="798718816711515431">"Prenosite aplikacije s telefona"</string>
+ <string name="title_app_streaming" msgid="2270331024626446950">"Dozvolite da aplikacija <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> pristupa ovim informacijama s telefona"</string>
<string name="summary_app_streaming" product="default" msgid="6105916810614498138">"Dozvolite da <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> omogući daljinski pristup uređaju <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong> radi pristupanja aplikacijama instaliranim na ovom telefonu kada je povezan s mrežom."</string>
<string name="summary_app_streaming" product="tablet" msgid="2996373715966272792">"Dozvolite da <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> omogući daljinski pristup uređaju <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong> radi pristupanja aplikacijama instaliranim na ovom tabletu kada je povezan s mrežom."</string>
<string name="summary_app_streaming" product="device" msgid="7614171699434639963">"Dozvolite da <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> omogući daljinski pristup uređaju <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong> radi pristupanja aplikacijama instaliranim na njemu kada je povezan s mrežom."</string>
+ <string name="helper_title_app_streaming" msgid="4151687003439969765">"Usluga na više uređaja"</string>
+ <string name="helper_summary_app_streaming" msgid="5344341720432827388">"Ova usluga se koristi za prijenos aplikacija između vaših uređaja"</string>
<string name="title_automotive_projection" msgid="3296005598978412847"></string>
<string name="summary_automotive_projection" msgid="8683801274662496164"></string>
- <string name="title_computer" msgid="4693714143506569253">"Dozvolite da aplikacija <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> pristupa ovim informacijama s vašeg telefona"</string>
+ <string name="title_computer" msgid="4693714143506569253">"Dozvolite aplikaciji <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> da pristupa ovim informacijama s vašeg telefona"</string>
<string name="summary_computer" msgid="3798467601598297062"></string>
+ <string name="permission_notification" msgid="693762568127741203">"Obavještenja"</string>
+ <string name="permission_notification_summary" msgid="4398672775023193663">"Može čitati sva obavještenja, uključujući informacije kao što su kontakti, poruke i fotografije"</string>
+ <string name="permission_storage" msgid="6831099350839392343">"Fotografije i mediji"</string>
+ <string name="permission_storage_summary" msgid="3918240895519506417"></string>
+ <string name="helper_title_computer" msgid="4671071173916176037">"Google Play usluge"</string>
+ <string name="helper_summary_computer" product="default" msgid="467996390095403648">"Ova usluga dijeli fotografije, medijski sadržaj i obavještenja s vašeg telefona na druge uređaje"</string>
+ <string name="helper_summary_computer" product="tablet" msgid="467996390095403648">"Ova usluga dijeli fotografije, medijski sadržaj i obavještenja s vašeg telefona na druge uređaje"</string>
<string name="profile_name_generic" msgid="6851028682723034988">"uređaj"</string>
<string name="summary_generic" msgid="2346762210105903720"></string>
<string name="consent_yes" msgid="8344487259618762872">"Dozvoli"</string>
<string name="consent_no" msgid="2640796915611404382">"Nemoj dozvoliti"</string>
+ <string name="consent_ok" msgid="3662376764371001106">"Uredu"</string>
<string name="permission_sync_confirmation_title" msgid="667074294393493186">"Prijenos odobrenja za aplikaciju na sat"</string>
<string name="permission_sync_summary" msgid="8873391306499120778">"Radi lakšeg postavljanja sata, aplikacije instalirane na satu tokom postavljanja će koristiti ista odobrenja kao i na telefonu.\n\n Ta odobrenja mogu uključivati pristup mikrofonu i lokaciji sata."</string>
</resources>
diff --git a/packages/CompanionDeviceManager/res/values-ca/strings.xml b/packages/CompanionDeviceManager/res/values-ca/strings.xml
index de7e225..0b18476 100644
--- a/packages/CompanionDeviceManager/res/values-ca/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-ca/strings.xml
@@ -22,18 +22,30 @@
<string name="chooser_title" msgid="2262294130493605839">"Tria un <xliff:g id="PROFILE_NAME">%1$s</xliff:g> perquè el gestioni <strong><xliff:g id="APP_NAME">%2$s</xliff:g></strong>"</string>
<string name="summary_watch" product="default" msgid="7113724443198337683">"<xliff:g id="APP_NAME">%1$s</xliff:g> tindrà permís per interaccionar amb les teves notificacions i accedir al telèfon, als SMS, als contactes i al calendari."</string>
<string name="summary_watch" product="tablet" msgid="7113724443198337683">"<xliff:g id="APP_NAME">%1$s</xliff:g> tindrà permís per interaccionar amb les teves notificacions i accedir al telèfon, als SMS, als contactes i al calendari."</string>
- <string name="title_app_streaming" msgid="4459136600249308574">"Vols permetre que <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> reprodueixi aplicacions en continu?"</string>
+ <string name="permission_apps" msgid="6142133265286656158">"Aplicacions"</string>
+ <string name="permission_apps_summary" msgid="798718816711515431">"Reprodueix en continu aplicacions del telèfon"</string>
+ <string name="title_app_streaming" msgid="2270331024626446950">"Permet que <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> accedeixi a aquesta informació del telèfon"</string>
<string name="summary_app_streaming" product="default" msgid="6105916810614498138">"Permet que <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> proporcioni accés remot a <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong> per accedir a les aplicacions instal·lades en aquest telèfon quan estigui connectat."</string>
<string name="summary_app_streaming" product="tablet" msgid="2996373715966272792">"Permet que <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> proporcioni accés remot a <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong> per accedir a les aplicacions instal·lades en aquesta tauleta quan estigui connectada."</string>
<string name="summary_app_streaming" product="device" msgid="7614171699434639963">"Permet que <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> proporcioni accés remot a <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong> per accedir a les aplicacions instal·lades en aquest dispositiu quan estigui connectat."</string>
+ <string name="helper_title_app_streaming" msgid="4151687003439969765">"Serveis multidispositiu"</string>
+ <string name="helper_summary_app_streaming" msgid="5344341720432827388">"Aquest servei s\'utilitza per reproduir en continu aplicacions entre dispositius"</string>
<string name="title_automotive_projection" msgid="3296005598978412847"></string>
<string name="summary_automotive_projection" msgid="8683801274662496164"></string>
<string name="title_computer" msgid="4693714143506569253">"Permet que <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> accedeixi a aquesta informació del telèfon"</string>
<string name="summary_computer" msgid="3798467601598297062"></string>
+ <string name="permission_notification" msgid="693762568127741203">"Notificacions"</string>
+ <string name="permission_notification_summary" msgid="4398672775023193663">"Pot llegir totes les notificacions, inclosa informació com ara els contactes, els missatges i les fotos"</string>
+ <string name="permission_storage" msgid="6831099350839392343">"Fotos i contingut multimèdia"</string>
+ <string name="permission_storage_summary" msgid="3918240895519506417"></string>
+ <string name="helper_title_computer" msgid="4671071173916176037">"Serveis de Google Play"</string>
+ <string name="helper_summary_computer" product="default" msgid="467996390095403648">"Aquest servei comparteix fotos, contingut multimèdia i notificacions amb altres dispositius des del teu telèfon"</string>
+ <string name="helper_summary_computer" product="tablet" msgid="467996390095403648">"Aquest servei comparteix fotos, contingut multimèdia i notificacions amb altres dispositius des del teu telèfon"</string>
<string name="profile_name_generic" msgid="6851028682723034988">"dispositiu"</string>
<string name="summary_generic" msgid="2346762210105903720"></string>
<string name="consent_yes" msgid="8344487259618762872">"Permet"</string>
<string name="consent_no" msgid="2640796915611404382">"No permetis"</string>
+ <string name="consent_ok" msgid="3662376764371001106">"D\'acord"</string>
<string name="permission_sync_confirmation_title" msgid="667074294393493186">"Transfereix els permisos de les aplicacions al teu rellotge"</string>
<string name="permission_sync_summary" msgid="8873391306499120778">"Per facilitar la configuració del rellotge, les aplicacions instal·lades al rellotge durant la configuració utilitzaran els mateixos permisos que al teu telèfon.\n\n Aquests permisos poden incloure l\'accés al micròfon i a la ubicació del rellotge."</string>
</resources>
diff --git a/packages/CompanionDeviceManager/res/values-cs/strings.xml b/packages/CompanionDeviceManager/res/values-cs/strings.xml
index f195e54..f89f17e 100644
--- a/packages/CompanionDeviceManager/res/values-cs/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-cs/strings.xml
@@ -22,18 +22,30 @@
<string name="chooser_title" msgid="2262294130493605839">"Vyberte zařízení <xliff:g id="PROFILE_NAME">%1$s</xliff:g>, které chcete spravovat pomocí aplikace <strong><xliff:g id="APP_NAME">%2$s</xliff:g></strong>"</string>
<string name="summary_watch" product="default" msgid="7113724443198337683">"Aplikace <xliff:g id="APP_NAME">%1$s</xliff:g> bude moci interagovat s vašimi oznámeními a získá přístup k telefonu, SMS, kontaktům a kalendáři."</string>
<string name="summary_watch" product="tablet" msgid="7113724443198337683">"Aplikace <xliff:g id="APP_NAME">%1$s</xliff:g> bude moci interagovat s vašimi oznámeními a získá přístup k telefonu, SMS, kontaktům a kalendáři."</string>
- <string name="title_app_streaming" msgid="4459136600249308574">"Povolit aplikaci <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> streamovat aplikace?"</string>
+ <string name="permission_apps" msgid="6142133265286656158">"Aplikace"</string>
+ <string name="permission_apps_summary" msgid="798718816711515431">"Streamujte aplikace v telefonu"</string>
+ <string name="title_app_streaming" msgid="2270331024626446950">"Povolte aplikaci <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> přístup k těmto informacím z vašeho telefonu"</string>
<string name="summary_app_streaming" product="default" msgid="6105916810614498138">"Povolit aplikaci <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> poskytovat <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong> vzdálený přístup k aplikacím nainstalovaným v tomto telefonu, když je připojen."</string>
<string name="summary_app_streaming" product="tablet" msgid="2996373715966272792">"Povolit aplikaci <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> poskytovat <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong> vzdálený přístup k aplikacím nainstalovaným v tomto tabletu, když je připojen."</string>
<string name="summary_app_streaming" product="device" msgid="7614171699434639963">"Povolit aplikaci <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> poskytovat <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong> vzdálený přístup k aplikacím nainstalovaným v tomto zařízení, když je připojeno."</string>
+ <string name="helper_title_app_streaming" msgid="4151687003439969765">"Služby pro více zařízení"</string>
+ <string name="helper_summary_app_streaming" msgid="5344341720432827388">"Tato služba slouží ke streamování aplikací mezi zařízeními"</string>
<string name="title_automotive_projection" msgid="3296005598978412847"></string>
<string name="summary_automotive_projection" msgid="8683801274662496164"></string>
<string name="title_computer" msgid="4693714143506569253">"Povolte aplikaci <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> přístup k těmto informacím z vašeho telefonu"</string>
<string name="summary_computer" msgid="3798467601598297062"></string>
+ <string name="permission_notification" msgid="693762568127741203">"Oznámení"</string>
+ <string name="permission_notification_summary" msgid="4398672775023193663">"Může číst veškerá oznámení včetně informací, jako jsou kontakty, zprávy a fotky"</string>
+ <string name="permission_storage" msgid="6831099350839392343">"Fotky a média"</string>
+ <string name="permission_storage_summary" msgid="3918240895519506417"></string>
+ <string name="helper_title_computer" msgid="4671071173916176037">"Služby Google Play"</string>
+ <string name="helper_summary_computer" product="default" msgid="467996390095403648">"Tato služba sdílí fotky, média a oznámení z telefonu do ostatních zařízení"</string>
+ <string name="helper_summary_computer" product="tablet" msgid="467996390095403648">"Tato služba sdílí fotky, média a oznámení z telefonu do ostatních zařízení"</string>
<string name="profile_name_generic" msgid="6851028682723034988">"zařízení"</string>
<string name="summary_generic" msgid="2346762210105903720"></string>
<string name="consent_yes" msgid="8344487259618762872">"Povolit"</string>
<string name="consent_no" msgid="2640796915611404382">"Nepovolovat"</string>
+ <string name="consent_ok" msgid="3662376764371001106">"OK"</string>
<string name="permission_sync_confirmation_title" msgid="667074294393493186">"Přesunout oprávnění aplikací do hodinek"</string>
<string name="permission_sync_summary" msgid="8873391306499120778">"Abychom vám usnadnili nastavení hodinek, aplikace nainstalované do hodinek během úvodního nastavení budou používat stejná oprávnění jako váš telefon.\n\n Tato oprávnění mohou zahrnovat přístup k mikrofonu a poloze hodinek."</string>
</resources>
diff --git a/packages/CompanionDeviceManager/res/values-da/strings.xml b/packages/CompanionDeviceManager/res/values-da/strings.xml
index a2aa5dd..e366bb9 100644
--- a/packages/CompanionDeviceManager/res/values-da/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-da/strings.xml
@@ -22,18 +22,30 @@
<string name="chooser_title" msgid="2262294130493605839">"Vælg den enhed (<xliff:g id="PROFILE_NAME">%1$s</xliff:g>), som skal administreres af <strong><xliff:g id="APP_NAME">%2$s</xliff:g></strong>"</string>
<string name="summary_watch" product="default" msgid="7113724443198337683">"<xliff:g id="APP_NAME">%1$s</xliff:g> får tilladelse til at interagere med dine notifikationer og adgang til dine tilladelser for Opkald, Sms, Kontakter og Kalender."</string>
<string name="summary_watch" product="tablet" msgid="7113724443198337683">"<xliff:g id="APP_NAME">%1$s</xliff:g> får tilladelse til at interagere med dine notifikationer og adgang til dine tilladelser for Opkald, Sms, Kontakter og Kalender."</string>
- <string name="title_app_streaming" msgid="4459136600249308574">"Vil du give <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> tilladelse til at streame apps?"</string>
+ <string name="permission_apps" msgid="6142133265286656158">"Apps"</string>
+ <string name="permission_apps_summary" msgid="798718816711515431">"Stream din telefons apps"</string>
+ <string name="title_app_streaming" msgid="2270331024626446950">"Giv <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> adgang til disse oplysninger fra din telefon"</string>
<string name="summary_app_streaming" product="default" msgid="6105916810614498138">"Giver <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> tilladelse til at fjernstyre apps, som er installeret på <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong>, når telefonen har forbindelse til internettet."</string>
<string name="summary_app_streaming" product="tablet" msgid="2996373715966272792">"Giver <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> tilladelse til at fjernstyre apps, som er installeret på <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong>, når tabletten har forbindelse til internettet."</string>
<string name="summary_app_streaming" product="device" msgid="7614171699434639963">"Giver <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> tilladelse til at fjernstyre apps, som er installeret på <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong>, når enheden har forbindelse til internettet."</string>
+ <string name="helper_title_app_streaming" msgid="4151687003439969765">"Tjenester, som kan tilsluttes en anden enhed"</string>
+ <string name="helper_summary_app_streaming" msgid="5344341720432827388">"Denne tjeneste anvendes til at caste apps mellem dine enheder"</string>
<string name="title_automotive_projection" msgid="3296005598978412847"></string>
<string name="summary_automotive_projection" msgid="8683801274662496164"></string>
<string name="title_computer" msgid="4693714143506569253">"Tillad, at <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> får adgang til disse oplysninger fra din telefon"</string>
<string name="summary_computer" msgid="3798467601598297062"></string>
+ <string name="permission_notification" msgid="693762568127741203">"Notifikationer"</string>
+ <string name="permission_notification_summary" msgid="4398672775023193663">"Kan læse alle notifikationer, herunder oplysninger som f.eks. kontakter, beskeder og billeder"</string>
+ <string name="permission_storage" msgid="6831099350839392343">"Billeder og medier"</string>
+ <string name="permission_storage_summary" msgid="3918240895519506417"></string>
+ <string name="helper_title_computer" msgid="4671071173916176037">"Google Play-tjenester"</string>
+ <string name="helper_summary_computer" product="default" msgid="467996390095403648">"Denne tjeneste deler billeder, medier og notifikationer fra din telefon til andre enheder"</string>
+ <string name="helper_summary_computer" product="tablet" msgid="467996390095403648">"Denne tjeneste deler billeder, medier og notifikationer fra din telefon til andre enheder"</string>
<string name="profile_name_generic" msgid="6851028682723034988">"enhed"</string>
<string name="summary_generic" msgid="2346762210105903720"></string>
<string name="consent_yes" msgid="8344487259618762872">"Tillad"</string>
<string name="consent_no" msgid="2640796915611404382">"Tillad ikke"</string>
+ <string name="consent_ok" msgid="3662376764371001106">"OK"</string>
<string name="permission_sync_confirmation_title" msgid="667074294393493186">"Overfør apptilladelser til dit ur"</string>
<string name="permission_sync_summary" msgid="8873391306499120778">"For at gøre det nemmere at konfigurere dit ur vil de apps, der installeres under konfigurationen, anvende de samme tilladelser som din telefon.\n\n Disse tilladelser kan omfatte adgang til dit urs mikrofon og lokation."</string>
</resources>
diff --git a/packages/CompanionDeviceManager/res/values-de/strings.xml b/packages/CompanionDeviceManager/res/values-de/strings.xml
index 2b5ab11..440e06b 100644
--- a/packages/CompanionDeviceManager/res/values-de/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-de/strings.xml
@@ -22,18 +22,30 @@
<string name="chooser_title" msgid="2262294130493605839">"Gerät (<xliff:g id="PROFILE_NAME">%1$s</xliff:g>) auswählen, das von <strong><xliff:g id="APP_NAME">%2$s</xliff:g></strong> verwaltet werden soll"</string>
<string name="summary_watch" product="default" msgid="7113724443198337683">"<xliff:g id="APP_NAME">%1$s</xliff:g> darf mit deinen Benachrichtigungen interagieren und auf die Berechtigungen „Telefon“, „SMS“, „Kontakte“ und „Kalender“ zugreifen."</string>
<string name="summary_watch" product="tablet" msgid="7113724443198337683">"<xliff:g id="APP_NAME">%1$s</xliff:g> darf mit deinen Benachrichtigungen interagieren und auf die Berechtigungen „Telefon“, „SMS“, „Kontakte“ und „Kalender“ zugreifen."</string>
- <string name="title_app_streaming" msgid="4459136600249308574">"Möchtest du <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> erlauben, Apps zu streamen?"</string>
+ <string name="permission_apps" msgid="6142133265286656158">"Apps"</string>
+ <string name="permission_apps_summary" msgid="798718816711515431">"Smartphone-Apps streamen"</string>
+ <string name="title_app_streaming" msgid="2270331024626446950">"<strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> Zugriff auf diese Informationen von deinem Smartphone gewähren"</string>
<string name="summary_app_streaming" product="default" msgid="6105916810614498138">"Besteht eine Verbindung, darf <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong> Remotezugriff auf die auf diesem Smartphone installierten Apps geben."</string>
<string name="summary_app_streaming" product="tablet" msgid="2996373715966272792">"Besteht eine Verbindung, darf <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong> Remotezugriff auf die auf diesem Tablet installierten Apps geben."</string>
<string name="summary_app_streaming" product="device" msgid="7614171699434639963">"Besteht eine Verbindung, darf <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong> Remotezugriff auf die auf diesem Gerät installierten Apps geben."</string>
+ <string name="helper_title_app_streaming" msgid="4151687003439969765">"Geräteübergreifende Dienste"</string>
+ <string name="helper_summary_app_streaming" msgid="5344341720432827388">"Dieser Dienst wird dazu verwendet, Apps zwischen deinen Geräten zu streamen"</string>
<string name="title_automotive_projection" msgid="3296005598978412847"></string>
<string name="summary_automotive_projection" msgid="8683801274662496164"></string>
<string name="title_computer" msgid="4693714143506569253">"<strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> Zugriff auf diese Informationen von deinem Smartphone gewähren"</string>
<string name="summary_computer" msgid="3798467601598297062"></string>
+ <string name="permission_notification" msgid="693762568127741203">"Benachrichtigungen"</string>
+ <string name="permission_notification_summary" msgid="4398672775023193663">"Kann alle Benachrichtigungen lesen, einschließlich Informationen wie Verträgen, Nachrichten und Fotos"</string>
+ <string name="permission_storage" msgid="6831099350839392343">"Fotos und Medien"</string>
+ <string name="permission_storage_summary" msgid="3918240895519506417"></string>
+ <string name="helper_title_computer" msgid="4671071173916176037">"Google Play-Dienste"</string>
+ <string name="helper_summary_computer" product="default" msgid="467996390095403648">"Dieser Dienst teilt Fotos, Medien und Benachrichtigungen von deinem Smartphone mit anderen Geräten"</string>
+ <string name="helper_summary_computer" product="tablet" msgid="467996390095403648">"Dieser Dienst teilt Fotos, Medien und Benachrichtigungen von deinem Smartphone mit anderen Geräten"</string>
<string name="profile_name_generic" msgid="6851028682723034988">"Gerät"</string>
<string name="summary_generic" msgid="2346762210105903720"></string>
<string name="consent_yes" msgid="8344487259618762872">"Zulassen"</string>
<string name="consent_no" msgid="2640796915611404382">"Nicht zulassen"</string>
+ <string name="consent_ok" msgid="3662376764371001106">"OK"</string>
<string name="permission_sync_confirmation_title" msgid="667074294393493186">"App-Berechtigungen auf Smartwatch übertragen"</string>
<string name="permission_sync_summary" msgid="8873391306499120778">"Damit sich deine Smartwatch leichter einrichten lässt, erhalten die Apps, die während der Einrichtung auf deiner Smartwatch installiert werden, automatisch die gleichen Berechtigungen wie deine Smartphone-Apps.\n\n Zu diesen Berechtigungen kann der Zugriff auf das Mikrofon und den Standort deiner Smartwatch gehören."</string>
</resources>
diff --git a/packages/CompanionDeviceManager/res/values-el/strings.xml b/packages/CompanionDeviceManager/res/values-el/strings.xml
index 339f85a..326527c 100644
--- a/packages/CompanionDeviceManager/res/values-el/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-el/strings.xml
@@ -22,18 +22,30 @@
<string name="chooser_title" msgid="2262294130493605839">"Επιλέξτε ένα προφίλ <xliff:g id="PROFILE_NAME">%1$s</xliff:g> για διαχείριση από την εφαρμογή <strong><xliff:g id="APP_NAME">%2$s</xliff:g></strong>"</string>
<string name="summary_watch" product="default" msgid="7113724443198337683">"Η εφαρμογή <xliff:g id="APP_NAME">%1$s</xliff:g> θα επιτρέπεται να αλληλεπιδρά με τις ειδοποιήσεις σας και να έχει πρόσβαση στις άδειες Τηλεφώνου, SMS, Επαφών και Ημερολογίου."</string>
<string name="summary_watch" product="tablet" msgid="7113724443198337683">"Η εφαρμογή <xliff:g id="APP_NAME">%1$s</xliff:g> θα επιτρέπεται να αλληλεπιδρά με τις ειδοποιήσεις σας και να έχει πρόσβαση στις άδειες Τηλεφώνου, SMS, Επαφών και Ημερολογίου."</string>
- <string name="title_app_streaming" msgid="4459136600249308574">"Να επιτρέπεται στην εφαρμογή <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> η ροή εφαρμογών;"</string>
+ <string name="permission_apps" msgid="6142133265286656158">"Εφαρμογές"</string>
+ <string name="permission_apps_summary" msgid="798718816711515431">"Μεταδώστε σε ροή τις εφαρμογές του τηλεφώνου σας"</string>
+ <string name="title_app_streaming" msgid="2270331024626446950">"Να επιτρέπεται στην εφαρμογή <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> η πρόσβαση σε αυτές τις πληροφορίες από το τηλέφωνό σας."</string>
<string name="summary_app_streaming" product="default" msgid="6105916810614498138">"Επιτρέψτε στην εφαρμογή <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> να παρέχει απομακρυσμένη πρόσβαση στη συσκευή <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong> κατά τη σύνδεση, προκειμένου να έχει πρόσβαση σε εφαρμογές που έχουν εγκατασταθεί σε αυτό το τηλέφωνο."</string>
<string name="summary_app_streaming" product="tablet" msgid="2996373715966272792">"Επιτρέψτε στην εφαρμογή <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> να παρέχει απομακρυσμένη πρόσβαση στη συσκευή <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong> κατά τη σύνδεση, προκειμένου να έχει πρόσβαση σε εφαρμογές που έχουν εγκατασταθεί σε αυτό το tablet."</string>
<string name="summary_app_streaming" product="device" msgid="7614171699434639963">"Επιτρέψτε στην εφαρμογή <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> να παρέχει απομακρυσμένη πρόσβαση στη συσκευή <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong> κατά τη σύνδεση, προκειμένου να έχει πρόσβαση σε εφαρμογές που έχουν εγκατασταθεί σε αυτήν τη συσκευή."</string>
+ <string name="helper_title_app_streaming" msgid="4151687003439969765">"Υπηρεσίες πολλών συσκευών"</string>
+ <string name="helper_summary_app_streaming" msgid="5344341720432827388">"Αυτή η υπηρεσία χρησιμοποιείται για τη ροή εφαρμογών μεταξύ των συσκευών σας"</string>
<string name="title_automotive_projection" msgid="3296005598978412847"></string>
<string name="summary_automotive_projection" msgid="8683801274662496164"></string>
<string name="title_computer" msgid="4693714143506569253">"Επιτρέψτε στην εφαρμογή <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> να έχει πρόσβαση σε αυτές τις πληροφορίες από το τηλέφωνό σας"</string>
<string name="summary_computer" msgid="3798467601598297062"></string>
+ <string name="permission_notification" msgid="693762568127741203">"Ειδοποιήσεις"</string>
+ <string name="permission_notification_summary" msgid="4398672775023193663">"Μπορεί να διαβάσει όλες τις ειδοποιήσεις, συμπεριλαμβανομένων πληροφοριών όπως επαφές, μηνύματα και φωτογραφίες"</string>
+ <string name="permission_storage" msgid="6831099350839392343">"Φωτογραφίες και μέσα"</string>
+ <string name="permission_storage_summary" msgid="3918240895519506417"></string>
+ <string name="helper_title_computer" msgid="4671071173916176037">"Υπηρεσίες Google Play"</string>
+ <string name="helper_summary_computer" product="default" msgid="467996390095403648">"Αυτή η υπηρεσία κοινοποιεί φωτογραφίες, πολυμέσα και ειδοποιήσεις από το τηλέφωνό σας σε άλλες συσκευές"</string>
+ <string name="helper_summary_computer" product="tablet" msgid="467996390095403648">"Αυτή η υπηρεσία κοινοποιεί φωτογραφίες, πολυμέσα και ειδοποιήσεις από το τηλέφωνό σας σε άλλες συσκευές"</string>
<string name="profile_name_generic" msgid="6851028682723034988">"συσκευή"</string>
<string name="summary_generic" msgid="2346762210105903720"></string>
<string name="consent_yes" msgid="8344487259618762872">"Να επιτρέπεται"</string>
<string name="consent_no" msgid="2640796915611404382">"Να μην επιτρέπεται"</string>
+ <string name="consent_ok" msgid="3662376764371001106">"OK"</string>
<string name="permission_sync_confirmation_title" msgid="667074294393493186">"Μεταφορά αδειών εφαρμογών στο ρολόι σας"</string>
<string name="permission_sync_summary" msgid="8873391306499120778">"Για να είναι πιο εύκολη η ρύθμιση του ρολογιού σας, οι εφαρμογές που εγκαθίστανται στο ρολόι σας κατά τη ρύθμιση, θα χρησιμοποιούν τις ίδιες άδειες με το τηλέφωνό σας.\n\n Στις άδειες ενδέχεται να περιλαμβάνεται άδεια πρόσβασης στο μικρόφωνο και την τοποθεσία του ρολογιού σας."</string>
</resources>
diff --git a/packages/CompanionDeviceManager/res/values-en-rAU/strings.xml b/packages/CompanionDeviceManager/res/values-en-rAU/strings.xml
index d596411..9b8f959 100644
--- a/packages/CompanionDeviceManager/res/values-en-rAU/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-en-rAU/strings.xml
@@ -22,18 +22,30 @@
<string name="chooser_title" msgid="2262294130493605839">"Choose a <xliff:g id="PROFILE_NAME">%1$s</xliff:g> to be managed by <strong><xliff:g id="APP_NAME">%2$s</xliff:g></strong>"</string>
<string name="summary_watch" product="default" msgid="7113724443198337683">"<xliff:g id="APP_NAME">%1$s</xliff:g> will be allowed to interact with your notifications and access your Phone, SMS, Contacts and Calendar permissions."</string>
<string name="summary_watch" product="tablet" msgid="7113724443198337683">"<xliff:g id="APP_NAME">%1$s</xliff:g> will be allowed to interact with your notifications and access your Phone, SMS, Contacts and Calendar permissions."</string>
- <string name="title_app_streaming" msgid="4459136600249308574">"Allow <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> to stream applications?"</string>
+ <string name="permission_apps" msgid="6142133265286656158">"Apps"</string>
+ <string name="permission_apps_summary" msgid="798718816711515431">"Stream your phone’s apps"</string>
+ <string name="title_app_streaming" msgid="2270331024626446950">"Allow <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> to access this information from your phone"</string>
<string name="summary_app_streaming" product="default" msgid="6105916810614498138">"Let <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> provide <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong> remote access to access to applications installed on this phone when connected."</string>
<string name="summary_app_streaming" product="tablet" msgid="2996373715966272792">"Let <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> provide <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong> remote access to access to applications installed on this tablet when connected."</string>
<string name="summary_app_streaming" product="device" msgid="7614171699434639963">"Let <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> provide <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong> remote access to access to applications installed on this device when connected."</string>
+ <string name="helper_title_app_streaming" msgid="4151687003439969765">"Cross-device services"</string>
+ <string name="helper_summary_app_streaming" msgid="5344341720432827388">"This service is used to stream apps between your devices"</string>
<string name="title_automotive_projection" msgid="3296005598978412847"></string>
<string name="summary_automotive_projection" msgid="8683801274662496164"></string>
<string name="title_computer" msgid="4693714143506569253">"Allow <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> to access this information from your phone"</string>
<string name="summary_computer" msgid="3798467601598297062"></string>
+ <string name="permission_notification" msgid="693762568127741203">"Notifications"</string>
+ <string name="permission_notification_summary" msgid="4398672775023193663">"Can read all notifications, including information such as contracts, messages and photos"</string>
+ <string name="permission_storage" msgid="6831099350839392343">"Photos and media"</string>
+ <string name="permission_storage_summary" msgid="3918240895519506417"></string>
+ <string name="helper_title_computer" msgid="4671071173916176037">"Google Play services"</string>
+ <string name="helper_summary_computer" product="default" msgid="467996390095403648">"This service shares photos, media and notifications from your phone to other devices"</string>
+ <string name="helper_summary_computer" product="tablet" msgid="467996390095403648">"This service shares photos, media and notifications from your phone to other devices"</string>
<string name="profile_name_generic" msgid="6851028682723034988">"device"</string>
<string name="summary_generic" msgid="2346762210105903720"></string>
<string name="consent_yes" msgid="8344487259618762872">"Allow"</string>
<string name="consent_no" msgid="2640796915611404382">"Don\'t allow"</string>
+ <string name="consent_ok" msgid="3662376764371001106">"OK"</string>
<string name="permission_sync_confirmation_title" msgid="667074294393493186">"Transfer app permissions to your watch"</string>
<string name="permission_sync_summary" msgid="8873391306499120778">"To make it easier to set up your watch, apps installed on your watch during setup will use the same permissions as your phone.\n\n These permissions may include access to your watch’s microphone and location."</string>
</resources>
diff --git a/packages/CompanionDeviceManager/res/values-en-rCA/strings.xml b/packages/CompanionDeviceManager/res/values-en-rCA/strings.xml
index d596411..9b8f959 100644
--- a/packages/CompanionDeviceManager/res/values-en-rCA/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-en-rCA/strings.xml
@@ -22,18 +22,30 @@
<string name="chooser_title" msgid="2262294130493605839">"Choose a <xliff:g id="PROFILE_NAME">%1$s</xliff:g> to be managed by <strong><xliff:g id="APP_NAME">%2$s</xliff:g></strong>"</string>
<string name="summary_watch" product="default" msgid="7113724443198337683">"<xliff:g id="APP_NAME">%1$s</xliff:g> will be allowed to interact with your notifications and access your Phone, SMS, Contacts and Calendar permissions."</string>
<string name="summary_watch" product="tablet" msgid="7113724443198337683">"<xliff:g id="APP_NAME">%1$s</xliff:g> will be allowed to interact with your notifications and access your Phone, SMS, Contacts and Calendar permissions."</string>
- <string name="title_app_streaming" msgid="4459136600249308574">"Allow <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> to stream applications?"</string>
+ <string name="permission_apps" msgid="6142133265286656158">"Apps"</string>
+ <string name="permission_apps_summary" msgid="798718816711515431">"Stream your phone’s apps"</string>
+ <string name="title_app_streaming" msgid="2270331024626446950">"Allow <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> to access this information from your phone"</string>
<string name="summary_app_streaming" product="default" msgid="6105916810614498138">"Let <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> provide <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong> remote access to access to applications installed on this phone when connected."</string>
<string name="summary_app_streaming" product="tablet" msgid="2996373715966272792">"Let <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> provide <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong> remote access to access to applications installed on this tablet when connected."</string>
<string name="summary_app_streaming" product="device" msgid="7614171699434639963">"Let <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> provide <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong> remote access to access to applications installed on this device when connected."</string>
+ <string name="helper_title_app_streaming" msgid="4151687003439969765">"Cross-device services"</string>
+ <string name="helper_summary_app_streaming" msgid="5344341720432827388">"This service is used to stream apps between your devices"</string>
<string name="title_automotive_projection" msgid="3296005598978412847"></string>
<string name="summary_automotive_projection" msgid="8683801274662496164"></string>
<string name="title_computer" msgid="4693714143506569253">"Allow <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> to access this information from your phone"</string>
<string name="summary_computer" msgid="3798467601598297062"></string>
+ <string name="permission_notification" msgid="693762568127741203">"Notifications"</string>
+ <string name="permission_notification_summary" msgid="4398672775023193663">"Can read all notifications, including information such as contracts, messages and photos"</string>
+ <string name="permission_storage" msgid="6831099350839392343">"Photos and media"</string>
+ <string name="permission_storage_summary" msgid="3918240895519506417"></string>
+ <string name="helper_title_computer" msgid="4671071173916176037">"Google Play services"</string>
+ <string name="helper_summary_computer" product="default" msgid="467996390095403648">"This service shares photos, media and notifications from your phone to other devices"</string>
+ <string name="helper_summary_computer" product="tablet" msgid="467996390095403648">"This service shares photos, media and notifications from your phone to other devices"</string>
<string name="profile_name_generic" msgid="6851028682723034988">"device"</string>
<string name="summary_generic" msgid="2346762210105903720"></string>
<string name="consent_yes" msgid="8344487259618762872">"Allow"</string>
<string name="consent_no" msgid="2640796915611404382">"Don\'t allow"</string>
+ <string name="consent_ok" msgid="3662376764371001106">"OK"</string>
<string name="permission_sync_confirmation_title" msgid="667074294393493186">"Transfer app permissions to your watch"</string>
<string name="permission_sync_summary" msgid="8873391306499120778">"To make it easier to set up your watch, apps installed on your watch during setup will use the same permissions as your phone.\n\n These permissions may include access to your watch’s microphone and location."</string>
</resources>
diff --git a/packages/CompanionDeviceManager/res/values-en-rGB/strings.xml b/packages/CompanionDeviceManager/res/values-en-rGB/strings.xml
index d596411..9b8f959 100644
--- a/packages/CompanionDeviceManager/res/values-en-rGB/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-en-rGB/strings.xml
@@ -22,18 +22,30 @@
<string name="chooser_title" msgid="2262294130493605839">"Choose a <xliff:g id="PROFILE_NAME">%1$s</xliff:g> to be managed by <strong><xliff:g id="APP_NAME">%2$s</xliff:g></strong>"</string>
<string name="summary_watch" product="default" msgid="7113724443198337683">"<xliff:g id="APP_NAME">%1$s</xliff:g> will be allowed to interact with your notifications and access your Phone, SMS, Contacts and Calendar permissions."</string>
<string name="summary_watch" product="tablet" msgid="7113724443198337683">"<xliff:g id="APP_NAME">%1$s</xliff:g> will be allowed to interact with your notifications and access your Phone, SMS, Contacts and Calendar permissions."</string>
- <string name="title_app_streaming" msgid="4459136600249308574">"Allow <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> to stream applications?"</string>
+ <string name="permission_apps" msgid="6142133265286656158">"Apps"</string>
+ <string name="permission_apps_summary" msgid="798718816711515431">"Stream your phone’s apps"</string>
+ <string name="title_app_streaming" msgid="2270331024626446950">"Allow <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> to access this information from your phone"</string>
<string name="summary_app_streaming" product="default" msgid="6105916810614498138">"Let <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> provide <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong> remote access to access to applications installed on this phone when connected."</string>
<string name="summary_app_streaming" product="tablet" msgid="2996373715966272792">"Let <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> provide <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong> remote access to access to applications installed on this tablet when connected."</string>
<string name="summary_app_streaming" product="device" msgid="7614171699434639963">"Let <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> provide <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong> remote access to access to applications installed on this device when connected."</string>
+ <string name="helper_title_app_streaming" msgid="4151687003439969765">"Cross-device services"</string>
+ <string name="helper_summary_app_streaming" msgid="5344341720432827388">"This service is used to stream apps between your devices"</string>
<string name="title_automotive_projection" msgid="3296005598978412847"></string>
<string name="summary_automotive_projection" msgid="8683801274662496164"></string>
<string name="title_computer" msgid="4693714143506569253">"Allow <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> to access this information from your phone"</string>
<string name="summary_computer" msgid="3798467601598297062"></string>
+ <string name="permission_notification" msgid="693762568127741203">"Notifications"</string>
+ <string name="permission_notification_summary" msgid="4398672775023193663">"Can read all notifications, including information such as contracts, messages and photos"</string>
+ <string name="permission_storage" msgid="6831099350839392343">"Photos and media"</string>
+ <string name="permission_storage_summary" msgid="3918240895519506417"></string>
+ <string name="helper_title_computer" msgid="4671071173916176037">"Google Play services"</string>
+ <string name="helper_summary_computer" product="default" msgid="467996390095403648">"This service shares photos, media and notifications from your phone to other devices"</string>
+ <string name="helper_summary_computer" product="tablet" msgid="467996390095403648">"This service shares photos, media and notifications from your phone to other devices"</string>
<string name="profile_name_generic" msgid="6851028682723034988">"device"</string>
<string name="summary_generic" msgid="2346762210105903720"></string>
<string name="consent_yes" msgid="8344487259618762872">"Allow"</string>
<string name="consent_no" msgid="2640796915611404382">"Don\'t allow"</string>
+ <string name="consent_ok" msgid="3662376764371001106">"OK"</string>
<string name="permission_sync_confirmation_title" msgid="667074294393493186">"Transfer app permissions to your watch"</string>
<string name="permission_sync_summary" msgid="8873391306499120778">"To make it easier to set up your watch, apps installed on your watch during setup will use the same permissions as your phone.\n\n These permissions may include access to your watch’s microphone and location."</string>
</resources>
diff --git a/packages/CompanionDeviceManager/res/values-en-rIN/strings.xml b/packages/CompanionDeviceManager/res/values-en-rIN/strings.xml
index d596411..9b8f959 100644
--- a/packages/CompanionDeviceManager/res/values-en-rIN/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-en-rIN/strings.xml
@@ -22,18 +22,30 @@
<string name="chooser_title" msgid="2262294130493605839">"Choose a <xliff:g id="PROFILE_NAME">%1$s</xliff:g> to be managed by <strong><xliff:g id="APP_NAME">%2$s</xliff:g></strong>"</string>
<string name="summary_watch" product="default" msgid="7113724443198337683">"<xliff:g id="APP_NAME">%1$s</xliff:g> will be allowed to interact with your notifications and access your Phone, SMS, Contacts and Calendar permissions."</string>
<string name="summary_watch" product="tablet" msgid="7113724443198337683">"<xliff:g id="APP_NAME">%1$s</xliff:g> will be allowed to interact with your notifications and access your Phone, SMS, Contacts and Calendar permissions."</string>
- <string name="title_app_streaming" msgid="4459136600249308574">"Allow <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> to stream applications?"</string>
+ <string name="permission_apps" msgid="6142133265286656158">"Apps"</string>
+ <string name="permission_apps_summary" msgid="798718816711515431">"Stream your phone’s apps"</string>
+ <string name="title_app_streaming" msgid="2270331024626446950">"Allow <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> to access this information from your phone"</string>
<string name="summary_app_streaming" product="default" msgid="6105916810614498138">"Let <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> provide <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong> remote access to access to applications installed on this phone when connected."</string>
<string name="summary_app_streaming" product="tablet" msgid="2996373715966272792">"Let <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> provide <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong> remote access to access to applications installed on this tablet when connected."</string>
<string name="summary_app_streaming" product="device" msgid="7614171699434639963">"Let <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> provide <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong> remote access to access to applications installed on this device when connected."</string>
+ <string name="helper_title_app_streaming" msgid="4151687003439969765">"Cross-device services"</string>
+ <string name="helper_summary_app_streaming" msgid="5344341720432827388">"This service is used to stream apps between your devices"</string>
<string name="title_automotive_projection" msgid="3296005598978412847"></string>
<string name="summary_automotive_projection" msgid="8683801274662496164"></string>
<string name="title_computer" msgid="4693714143506569253">"Allow <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> to access this information from your phone"</string>
<string name="summary_computer" msgid="3798467601598297062"></string>
+ <string name="permission_notification" msgid="693762568127741203">"Notifications"</string>
+ <string name="permission_notification_summary" msgid="4398672775023193663">"Can read all notifications, including information such as contracts, messages and photos"</string>
+ <string name="permission_storage" msgid="6831099350839392343">"Photos and media"</string>
+ <string name="permission_storage_summary" msgid="3918240895519506417"></string>
+ <string name="helper_title_computer" msgid="4671071173916176037">"Google Play services"</string>
+ <string name="helper_summary_computer" product="default" msgid="467996390095403648">"This service shares photos, media and notifications from your phone to other devices"</string>
+ <string name="helper_summary_computer" product="tablet" msgid="467996390095403648">"This service shares photos, media and notifications from your phone to other devices"</string>
<string name="profile_name_generic" msgid="6851028682723034988">"device"</string>
<string name="summary_generic" msgid="2346762210105903720"></string>
<string name="consent_yes" msgid="8344487259618762872">"Allow"</string>
<string name="consent_no" msgid="2640796915611404382">"Don\'t allow"</string>
+ <string name="consent_ok" msgid="3662376764371001106">"OK"</string>
<string name="permission_sync_confirmation_title" msgid="667074294393493186">"Transfer app permissions to your watch"</string>
<string name="permission_sync_summary" msgid="8873391306499120778">"To make it easier to set up your watch, apps installed on your watch during setup will use the same permissions as your phone.\n\n These permissions may include access to your watch’s microphone and location."</string>
</resources>
diff --git a/packages/CompanionDeviceManager/res/values-en-rXC/strings.xml b/packages/CompanionDeviceManager/res/values-en-rXC/strings.xml
index 9f17a89..8bd1c4a 100644
--- a/packages/CompanionDeviceManager/res/values-en-rXC/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-en-rXC/strings.xml
@@ -22,18 +22,30 @@
<string name="chooser_title" msgid="2262294130493605839">"Choose a <xliff:g id="PROFILE_NAME">%1$s</xliff:g> to be managed by <strong><xliff:g id="APP_NAME">%2$s</xliff:g></strong>"</string>
<string name="summary_watch" product="default" msgid="7113724443198337683">"<xliff:g id="APP_NAME">%1$s</xliff:g> will be allowed to interact with your notifications and access your Phone, SMS, Contacts and Calendar permissions."</string>
<string name="summary_watch" product="tablet" msgid="7113724443198337683">"<xliff:g id="APP_NAME">%1$s</xliff:g> will be allowed to interact with your notifications and access your Phone, SMS, Contacts and Calendar permissions."</string>
- <string name="title_app_streaming" msgid="4459136600249308574">"Allow <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> to stream applications?"</string>
+ <string name="permission_apps" msgid="6142133265286656158">"Apps"</string>
+ <string name="permission_apps_summary" msgid="798718816711515431">"Stream your phone’s apps"</string>
+ <string name="title_app_streaming" msgid="2270331024626446950">"Allow <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> to access this information from your phone"</string>
<string name="summary_app_streaming" product="default" msgid="6105916810614498138">"Let <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> to provide <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong> remote access to access to applications installed on this phone when connected."</string>
<string name="summary_app_streaming" product="tablet" msgid="2996373715966272792">"Let <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> to provide <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong> remote access to access to applications installed on this tablet when connected."</string>
<string name="summary_app_streaming" product="device" msgid="7614171699434639963">"Let <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> to provide <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong> remote access to access to applications installed on this device when connected."</string>
+ <string name="helper_title_app_streaming" msgid="4151687003439969765">"Cross-device services"</string>
+ <string name="helper_summary_app_streaming" msgid="5344341720432827388">"This service is used to stream apps between your devices"</string>
<string name="title_automotive_projection" msgid="3296005598978412847"></string>
<string name="summary_automotive_projection" msgid="8683801274662496164"></string>
<string name="title_computer" msgid="4693714143506569253">"Allow <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> to access this information from your phone"</string>
<string name="summary_computer" msgid="3798467601598297062"></string>
+ <string name="permission_notification" msgid="693762568127741203">"Notifications"</string>
+ <string name="permission_notification_summary" msgid="4398672775023193663">"Can read all notifications, including information like contracts, messages, and photos"</string>
+ <string name="permission_storage" msgid="6831099350839392343">"Photos and media"</string>
+ <string name="permission_storage_summary" msgid="3918240895519506417"></string>
+ <string name="helper_title_computer" msgid="4671071173916176037">"Google Play services"</string>
+ <string name="helper_summary_computer" product="default" msgid="467996390095403648">"This service shares photos, media, and notifications form your phone to other devices"</string>
+ <string name="helper_summary_computer" product="tablet" msgid="467996390095403648">"This service shares photos, media, and notifications form your phone to other devices"</string>
<string name="profile_name_generic" msgid="6851028682723034988">"device"</string>
<string name="summary_generic" msgid="2346762210105903720"></string>
<string name="consent_yes" msgid="8344487259618762872">"Allow"</string>
<string name="consent_no" msgid="2640796915611404382">"Don’t allow"</string>
+ <string name="consent_ok" msgid="3662376764371001106">"OK"</string>
<string name="permission_sync_confirmation_title" msgid="667074294393493186">"Transfer app permissions to your watch"</string>
<string name="permission_sync_summary" msgid="8873391306499120778">"To make it easier to set up your watch, apps installed on your watch during setup will use the same permissions as your phone.\n\n These permissions may include access to your watch’s microphone and location."</string>
</resources>
diff --git a/packages/CompanionDeviceManager/res/values-es-rUS/strings.xml b/packages/CompanionDeviceManager/res/values-es-rUS/strings.xml
index 5423d3e..e5b22a2 100644
--- a/packages/CompanionDeviceManager/res/values-es-rUS/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-es-rUS/strings.xml
@@ -22,18 +22,30 @@
<string name="chooser_title" msgid="2262294130493605839">"Elige un <xliff:g id="PROFILE_NAME">%1$s</xliff:g> para que <strong><xliff:g id="APP_NAME">%2$s</xliff:g></strong> lo administre"</string>
<string name="summary_watch" product="default" msgid="7113724443198337683">"<xliff:g id="APP_NAME">%1$s</xliff:g> podrá interactuar con tus notificaciones y acceder a los permisos de Teléfono, SMS, Contactos y Calendario."</string>
<string name="summary_watch" product="tablet" msgid="7113724443198337683">"<xliff:g id="APP_NAME">%1$s</xliff:g> podrá interactuar con tus notificaciones y acceder a los permisos de Teléfono, SMS, Contactos y Calendario."</string>
- <string name="title_app_streaming" msgid="4459136600249308574">"¿Deseas permitir que <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> transmita aplicaciones?"</string>
+ <string name="permission_apps" msgid="6142133265286656158">"Apps"</string>
+ <string name="permission_apps_summary" msgid="798718816711515431">"Transmitir las apps de tu teléfono"</string>
+ <string name="title_app_streaming" msgid="2270331024626446950">"Permite que <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> acceda a esta información de tu teléfono"</string>
<string name="summary_app_streaming" product="default" msgid="6105916810614498138">"Permite que <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> proporcione a <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong> acceso remoto a las aplicaciones instaladas en este teléfono cuando esté conectado."</string>
<string name="summary_app_streaming" product="tablet" msgid="2996373715966272792">"Permite que <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> proporcione <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong> acceso remoto a las aplicaciones instaladas en esta tablet cuando esté conectada."</string>
<string name="summary_app_streaming" product="device" msgid="7614171699434639963">"Permite que <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> proporcione a <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong> acceso remoto a las aplicaciones instaladas en este dispositivo cuando esté conectado."</string>
+ <string name="helper_title_app_streaming" msgid="4151687003439969765">"Servicios multidispositivo"</string>
+ <string name="helper_summary_app_streaming" msgid="5344341720432827388">"Este servicio se utiliza para transmitir apps entre tus dispositivos"</string>
<string name="title_automotive_projection" msgid="3296005598978412847"></string>
<string name="summary_automotive_projection" msgid="8683801274662496164"></string>
<string name="title_computer" msgid="4693714143506569253">"Permite que <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> acceda a esta información de tu teléfono"</string>
<string name="summary_computer" msgid="3798467601598297062"></string>
+ <string name="permission_notification" msgid="693762568127741203">"Notificaciones"</string>
+ <string name="permission_notification_summary" msgid="4398672775023193663">"Puede leer todas las notificaciones, incluso con información como contratos, mensajes y fotos"</string>
+ <string name="permission_storage" msgid="6831099350839392343">"Fotos y contenido multimedia"</string>
+ <string name="permission_storage_summary" msgid="3918240895519506417"></string>
+ <string name="helper_title_computer" msgid="4671071173916176037">"Servicios de Google Play"</string>
+ <string name="helper_summary_computer" product="default" msgid="467996390095403648">"Este servicio comparte fotos, contenido multimedia y notificaciones de tu teléfono a otros dispositivos"</string>
+ <string name="helper_summary_computer" product="tablet" msgid="467996390095403648">"Este servicio comparte fotos, contenido multimedia y notificaciones de tu teléfono a otros dispositivos"</string>
<string name="profile_name_generic" msgid="6851028682723034988">"dispositivo"</string>
<string name="summary_generic" msgid="2346762210105903720"></string>
<string name="consent_yes" msgid="8344487259618762872">"Permitir"</string>
<string name="consent_no" msgid="2640796915611404382">"No permitir"</string>
+ <string name="consent_ok" msgid="3662376764371001106">"Aceptar"</string>
<string name="permission_sync_confirmation_title" msgid="667074294393493186">"Transfiere los permisos de la app a tu reloj"</string>
<string name="permission_sync_summary" msgid="8873391306499120778">"Para que sea más fácil configurar tu reloj, las apps que se instalen en este durante la configuración usarán los mismos permisos que tu teléfono.\n\n Es posible que estos permisos incluyan el acceso al micrófono y a la ubicación del reloj."</string>
</resources>
diff --git a/packages/CompanionDeviceManager/res/values-es/strings.xml b/packages/CompanionDeviceManager/res/values-es/strings.xml
index ccbdd25..1a988e9 100644
--- a/packages/CompanionDeviceManager/res/values-es/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-es/strings.xml
@@ -22,18 +22,30 @@
<string name="chooser_title" msgid="2262294130493605839">"Elige un <xliff:g id="PROFILE_NAME">%1$s</xliff:g> para gestionarlo con <strong><xliff:g id="APP_NAME">%2$s</xliff:g></strong>"</string>
<string name="summary_watch" product="default" msgid="7113724443198337683">"<xliff:g id="APP_NAME">%1$s</xliff:g> podrá interactuar con tus notificaciones y acceder a tus permisos de teléfono, SMS, contactos y calendario."</string>
<string name="summary_watch" product="tablet" msgid="7113724443198337683">"<xliff:g id="APP_NAME">%1$s</xliff:g> podrá interactuar con tus notificaciones y acceder a tus permisos de teléfono, SMS, contactos y calendario."</string>
- <string name="title_app_streaming" msgid="4459136600249308574">"¿Permitir que <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> inicie aplicaciones?"</string>
+ <string name="permission_apps" msgid="6142133265286656158">"Aplicaciones"</string>
+ <string name="permission_apps_summary" msgid="798718816711515431">"Emite las aplicaciones de tu teléfono"</string>
+ <string name="title_app_streaming" msgid="2270331024626446950">"Permitir que <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> acceda a esta información desde tu teléfono"</string>
<string name="summary_app_streaming" product="default" msgid="6105916810614498138">"Permite que <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> acceda de forma remota a las aplicaciones instaladas en este teléfono cuando <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong> esté conectado a Internet."</string>
<string name="summary_app_streaming" product="tablet" msgid="2996373715966272792">"Permite que <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> acceda de forma remota a las aplicaciones instaladas en este tablet cuando <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong> esté conectado a Internet."</string>
<string name="summary_app_streaming" product="device" msgid="7614171699434639963">"Permite que <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> acceda de forma remota a las aplicaciones instaladas en este dispositivo cuando <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong> esté conectado a Internet."</string>
+ <string name="helper_title_app_streaming" msgid="4151687003439969765">"Servicios multidispositivo"</string>
+ <string name="helper_summary_app_streaming" msgid="5344341720432827388">"Este servicio se usa para emitir aplicaciones en otros dispositivos tuyos"</string>
<string name="title_automotive_projection" msgid="3296005598978412847"></string>
<string name="summary_automotive_projection" msgid="8683801274662496164"></string>
<string name="title_computer" msgid="4693714143506569253">"Permitir que <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> acceda a esta información desde tu teléfono"</string>
<string name="summary_computer" msgid="3798467601598297062"></string>
+ <string name="permission_notification" msgid="693762568127741203">"Notificaciones"</string>
+ <string name="permission_notification_summary" msgid="4398672775023193663">"Puede leer todas las notificaciones, incluida información como contactos, mensajes y fotos"</string>
+ <string name="permission_storage" msgid="6831099350839392343">"Fotos y elementos multimedia"</string>
+ <string name="permission_storage_summary" msgid="3918240895519506417"></string>
+ <string name="helper_title_computer" msgid="4671071173916176037">"Servicios de Google Play"</string>
+ <string name="helper_summary_computer" product="default" msgid="467996390095403648">"Este servicio comparte fotos, archivos multimedia y notificaciones de tu teléfono con otros dispositivos"</string>
+ <string name="helper_summary_computer" product="tablet" msgid="467996390095403648">"Este servicio comparte fotos, archivos multimedia y notificaciones de tu teléfono con otros dispositivos"</string>
<string name="profile_name_generic" msgid="6851028682723034988">"dispositivo"</string>
<string name="summary_generic" msgid="2346762210105903720"></string>
<string name="consent_yes" msgid="8344487259618762872">"Permitir"</string>
<string name="consent_no" msgid="2640796915611404382">"No permitir"</string>
+ <string name="consent_ok" msgid="3662376764371001106">"Aceptar"</string>
<string name="permission_sync_confirmation_title" msgid="667074294393493186">"Transferir permisos de aplicaciones a tu reloj"</string>
<string name="permission_sync_summary" msgid="8873391306499120778">"Para configurar fácilmente tu reloj, las aplicaciones que instales en él durante la configuración usarán los mismos permisos que tengan en tu teléfono.\n\n Estos permisos pueden incluir acceso al micrófono y a la ubicación del reloj."</string>
</resources>
diff --git a/packages/CompanionDeviceManager/res/values-et/strings.xml b/packages/CompanionDeviceManager/res/values-et/strings.xml
index d8f1e99..f3b8ea9 100644
--- a/packages/CompanionDeviceManager/res/values-et/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-et/strings.xml
@@ -22,18 +22,30 @@
<string name="chooser_title" msgid="2262294130493605839">"Valige seade <xliff:g id="PROFILE_NAME">%1$s</xliff:g>, mida haldab rakendus <strong><xliff:g id="APP_NAME">%2$s</xliff:g></strong>"</string>
<string name="summary_watch" product="default" msgid="7113724443198337683">"<xliff:g id="APP_NAME">%1$s</xliff:g> saab kasutada teie märguandeid ning pääseda juurde teie telefoni, SMS-ide, kontaktide ja kalendri lubadele."</string>
<string name="summary_watch" product="tablet" msgid="7113724443198337683">"<xliff:g id="APP_NAME">%1$s</xliff:g> saab kasutada teie märguandeid ning pääseda juurde teie telefoni, SMS-ide, kontaktide ja kalendri lubadele."</string>
- <string name="title_app_streaming" msgid="4459136600249308574">"Kas lubada rakendusel <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> rakendusi voogesituse kaudu üle kanda?"</string>
+ <string name="permission_apps" msgid="6142133265286656158">"Rakendused"</string>
+ <string name="permission_apps_summary" msgid="798718816711515431">"Telefoni rakenduste voogesitamine"</string>
+ <string name="title_app_streaming" msgid="2270331024626446950">"Lubage rakendusel <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> pääseda teie telefonis juurde sellele teabele"</string>
<string name="summary_app_streaming" product="default" msgid="6105916810614498138">"Rakendusel <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> lubatakse seadmele <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong> pakkuda kaugjuurdepääsu, et ühendatuna pääseda juurde sellesse telefoni installitud rakendustele."</string>
<string name="summary_app_streaming" product="tablet" msgid="2996373715966272792">"Rakendusel <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> lubatakse seadmele <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong> pakkuda kaugjuurdepääsu, et ühendatuna pääseda juurde sellesse tahvelarvutisse installitud rakendustele."</string>
<string name="summary_app_streaming" product="device" msgid="7614171699434639963">"Rakendusel <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> lubatakse seadmele <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong> pakkuda kaugjuurdepääsu, et ühendatuna pääseda juurde sellesse seadmesse installitud rakendustele."</string>
+ <string name="helper_title_app_streaming" msgid="4151687003439969765">"Seadmeülesed teenused"</string>
+ <string name="helper_summary_app_streaming" msgid="5344341720432827388">"Seda teenust kasutatakse rakenduste voogesitamiseks teie seadmete vahel"</string>
<string name="title_automotive_projection" msgid="3296005598978412847"></string>
<string name="summary_automotive_projection" msgid="8683801274662496164"></string>
<string name="title_computer" msgid="4693714143506569253">"Lubage rakendusel <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> pääseda teie telefonis juurde sellele teabele"</string>
<string name="summary_computer" msgid="3798467601598297062"></string>
+ <string name="permission_notification" msgid="693762568127741203">"Märguanded"</string>
+ <string name="permission_notification_summary" msgid="4398672775023193663">"Kõikide märguannete, sealhulgas teabe, nagu kontaktid, sõnumid ja fotod, lugemine"</string>
+ <string name="permission_storage" msgid="6831099350839392343">"Fotod ja meedia"</string>
+ <string name="permission_storage_summary" msgid="3918240895519506417"></string>
+ <string name="helper_title_computer" msgid="4671071173916176037">"Google Play teenused"</string>
+ <string name="helper_summary_computer" product="default" msgid="467996390095403648">"See teenus jagab muude seadmetega teie telefonist pärit fotosid, meediat ja märguandeid"</string>
+ <string name="helper_summary_computer" product="tablet" msgid="467996390095403648">"See teenus jagab muude seadmetega teie telefonist pärit fotosid, meediat ja märguandeid"</string>
<string name="profile_name_generic" msgid="6851028682723034988">"seade"</string>
<string name="summary_generic" msgid="2346762210105903720"></string>
<string name="consent_yes" msgid="8344487259618762872">"Luba"</string>
<string name="consent_no" msgid="2640796915611404382">"Ära luba"</string>
+ <string name="consent_ok" msgid="3662376764371001106">"OK"</string>
<string name="permission_sync_confirmation_title" msgid="667074294393493186">"Rakenduste lubade kellale ülekandmine"</string>
<string name="permission_sync_summary" msgid="8873391306499120778">"Selleks et muuta kella seadistamine lihtsamaks, kasutavad teie kellas seadistamise ajal installitud rakendused samasid lubasid, mis neile telefonis antud on.\n\n Need load võivad hõlmata juurdepääsuluba kella mikrofonile ja asukohale."</string>
</resources>
diff --git a/packages/CompanionDeviceManager/res/values-eu/strings.xml b/packages/CompanionDeviceManager/res/values-eu/strings.xml
index de76824..0d4f073 100644
--- a/packages/CompanionDeviceManager/res/values-eu/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-eu/strings.xml
@@ -22,18 +22,30 @@
<string name="chooser_title" msgid="2262294130493605839">"Aukeratu <strong><xliff:g id="APP_NAME">%2$s</xliff:g></strong> aplikazioak kudeatu beharreko <xliff:g id="PROFILE_NAME">%1$s</xliff:g>"</string>
<string name="summary_watch" product="default" msgid="7113724443198337683">"Jakinarazpenekin interakzioan aritzeko eta telefonoa, SMSak, kontaktuak eta egutegia erabiltzeko baimenak izango ditu <xliff:g id="APP_NAME">%1$s</xliff:g> aplikazioak."</string>
<string name="summary_watch" product="tablet" msgid="7113724443198337683">"Jakinarazpenekin interakzioan aritzeko eta telefonoa, SMSak, kontaktuak eta egutegia erabiltzeko baimenak izango ditu <xliff:g id="APP_NAME">%1$s</xliff:g> aplikazioak."</string>
- <string name="title_app_streaming" msgid="4459136600249308574">"Aplikazioak igortzeko baimena eman nahi diozu <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> aplikazioari?"</string>
+ <string name="permission_apps" msgid="6142133265286656158">"Aplikazioak"</string>
+ <string name="permission_apps_summary" msgid="798718816711515431">"Igorri zuzenean telefonoko aplikazioak"</string>
+ <string name="title_app_streaming" msgid="2270331024626446950">"Eman informazioa telefonotik hartzeko baimena <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> aplikazioari"</string>
<string name="summary_app_streaming" product="default" msgid="6105916810614498138">"Utzi <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> aplikazioari <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong> urrunetik atzitzen, telefonoa konektatuta dagoenean bertan instalatuta dauden aplikazioetarako sarbidea izateko."</string>
<string name="summary_app_streaming" product="tablet" msgid="2996373715966272792">"Utzi <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> aplikazioari <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong> urrunetik atzitzen, tableta konektatuta dagoenean bertan instalatuta dauden aplikazioetarako sarbidea izateko."</string>
<string name="summary_app_streaming" product="device" msgid="7614171699434639963">"Utzi <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> aplikazioari <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong> urrunetik atzitzen, gailua konektatuta dagoenean bertan instalatuta dauden aplikazioetarako sarbidea izateko."</string>
+ <string name="helper_title_app_streaming" msgid="4151687003439969765">"Gailu bat baino gehiagotarako zerbitzuak"</string>
+ <string name="helper_summary_app_streaming" msgid="5344341720432827388">"Gailuen artean aplikazioak igortzeko erabiltzen da zerbitzua"</string>
<string name="title_automotive_projection" msgid="3296005598978412847"></string>
<string name="summary_automotive_projection" msgid="8683801274662496164"></string>
<string name="title_computer" msgid="4693714143506569253">"Eman informazio hori telefonotik hartzeko baimena <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> aplikazioari"</string>
<string name="summary_computer" msgid="3798467601598297062"></string>
+ <string name="permission_notification" msgid="693762568127741203">"Jakinarazpenak"</string>
+ <string name="permission_notification_summary" msgid="4398672775023193663">"Jakinarazpen guztiak irakur ditzake; besteak beste, kontaktuak, mezuak, argazkiak eta antzeko informazioa"</string>
+ <string name="permission_storage" msgid="6831099350839392343">"Argazkiak eta multimedia-edukia"</string>
+ <string name="permission_storage_summary" msgid="3918240895519506417"></string>
+ <string name="helper_title_computer" msgid="4671071173916176037">"Google Play Services"</string>
+ <string name="helper_summary_computer" product="default" msgid="467996390095403648">"Zerbitzuak telefonoko argazkiak, multimedia-edukia eta jakinarazpenak partekatzen ditu beste gailuekin"</string>
+ <string name="helper_summary_computer" product="tablet" msgid="467996390095403648">"Zerbitzuak telefonoko argazkiak, multimedia-edukia eta jakinarazpenak partekatzen ditu beste gailuekin"</string>
<string name="profile_name_generic" msgid="6851028682723034988">"gailua"</string>
<string name="summary_generic" msgid="2346762210105903720"></string>
<string name="consent_yes" msgid="8344487259618762872">"Eman baimena"</string>
<string name="consent_no" msgid="2640796915611404382">"Ez eman baimenik"</string>
+ <string name="consent_ok" msgid="3662376764371001106">"Ados"</string>
<string name="permission_sync_confirmation_title" msgid="667074294393493186">"Transferitu aplikazio-baimenak erlojura"</string>
<string name="permission_sync_summary" msgid="8873391306499120778">"Erlojua errazago konfiguratzeko, konfigurazio-prozesua abian zen bitartean erlojuan instalatutako aplikazioek telefonoak darabiltzan baimen berak erabiliko dituzte.\n\n Baliteke baimen horien artean erlojuaren mikrofonoa eta kokapena atzitzeko baimenak egotea."</string>
</resources>
diff --git a/packages/CompanionDeviceManager/res/values-fa/strings.xml b/packages/CompanionDeviceManager/res/values-fa/strings.xml
index 65ed2dd..cb14c27 100644
--- a/packages/CompanionDeviceManager/res/values-fa/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-fa/strings.xml
@@ -22,18 +22,30 @@
<string name="chooser_title" msgid="2262294130493605839">"انتخاب <xliff:g id="PROFILE_NAME">%1$s</xliff:g> برای مدیریت کردن با <strong><xliff:g id="APP_NAME">%2$s</xliff:g></strong>"</string>
<string name="summary_watch" product="default" msgid="7113724443198337683">"<xliff:g id="APP_NAME">%1$s</xliff:g> میتواند با اعلانهای شما تعامل داشته باشد و به اجازههای «تلفن»، «پیامک»، «مخاطبین»، و «تقویم» دسترسی پیدا کند."</string>
<string name="summary_watch" product="tablet" msgid="7113724443198337683">"<xliff:g id="APP_NAME">%1$s</xliff:g> میتواند با اعلانهای شما تعامل داشته باشد و به اجازههای «تلفن»، «پیامک»، «مخاطبین»، و «تقویم» دسترسی پیدا کند."</string>
- <string name="title_app_streaming" msgid="4459136600249308574">"به <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> اجازه میدهید برنامهها را جاریسازی کند؟"</string>
+ <string name="permission_apps" msgid="6142133265286656158">"برنامهها"</string>
+ <string name="permission_apps_summary" msgid="798718816711515431">"جاریسازی برنامههای تلفن"</string>
+ <string name="title_app_streaming" msgid="2270331024626446950">"اجازه دادن به <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> برای دسترسی به اطلاعات تلفن"</string>
<string name="summary_app_streaming" product="default" msgid="6105916810614498138">"به <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> اجازه میدهد برای <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong> دسترسی ازراهدور ارائه دهد تا دستگاه موردنظر بتواند هنگام اتصال، به برنامههای نصبشده در این تلفن دسترسی داشته باشد."</string>
<string name="summary_app_streaming" product="tablet" msgid="2996373715966272792">"به <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> اجازه میدهد برای <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong> دسترسی ازراهدور ارائه دهد تا دستگاه موردنظر بتواند هنگام اتصال، به برنامههای نصبشده در این رایانه لوحی دسترسی داشته باشد."</string>
<string name="summary_app_streaming" product="device" msgid="7614171699434639963">"به <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> اجازه میدهد برای <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong> دسترسی ازراهدور ارائه دهد تا دستگاه موردنظر بتواند هنگام اتصال، به برنامههای نصبشده در این دستگاه دسترسی داشته باشد."</string>
+ <string name="helper_title_app_streaming" msgid="4151687003439969765">"سرویسهای بیندستگاهی"</string>
+ <string name="helper_summary_app_streaming" msgid="5344341720432827388">"از این سرویس برای جاریسازی برنامهها میان دستگاههایتان استفاده میشود"</string>
<string name="title_automotive_projection" msgid="3296005598978412847"></string>
<string name="summary_automotive_projection" msgid="8683801274662496164"></string>
<string name="title_computer" msgid="4693714143506569253">"<strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> مجاز میشود به این اطلاعات در دستگاهتان دسترسی پیدا کند"</string>
<string name="summary_computer" msgid="3798467601598297062"></string>
+ <string name="permission_notification" msgid="693762568127741203">"اعلانها"</string>
+ <string name="permission_notification_summary" msgid="4398672775023193663">"میتواند همه اعلانها، ازجمله اطلاعاتی مثل قراردادها، پیامها، و عکسها را بخواند"</string>
+ <string name="permission_storage" msgid="6831099350839392343">"عکسها و رسانهها"</string>
+ <string name="permission_storage_summary" msgid="3918240895519506417"></string>
+ <string name="helper_title_computer" msgid="4671071173916176037">"خدمات Google Play"</string>
+ <string name="helper_summary_computer" product="default" msgid="467996390095403648">"این سرویس عکسها، رسانه، و اعلانهای تلفن را با دستگاههای دیگر همرسانی میکند"</string>
+ <string name="helper_summary_computer" product="tablet" msgid="467996390095403648">"این سرویس عکسها، رسانه، و اعلانهای تلفن را با دستگاههای دیگر همرسانی میکند"</string>
<string name="profile_name_generic" msgid="6851028682723034988">"دستگاه"</string>
<string name="summary_generic" msgid="2346762210105903720"></string>
<string name="consent_yes" msgid="8344487259618762872">"مجاز است"</string>
<string name="consent_no" msgid="2640796915611404382">"مجاز نبودن"</string>
+ <string name="consent_ok" msgid="3662376764371001106">"تأیید"</string>
<string name="permission_sync_confirmation_title" msgid="667074294393493186">"انتقال اجازههای برنامه به ساعت"</string>
<string name="permission_sync_summary" msgid="8873391306499120778">"برای آسانتر کردن راهاندازی ساعت، برنامههای نصبشده در ساعت درحین راهاندازی از همان اجازههای تلفن استفاده خواهند کرد.\n\n ممکن است این اجازهها شامل دسترسی به میکروفون و مکان ساعت باشد."</string>
</resources>
diff --git a/packages/CompanionDeviceManager/res/values-fi/strings.xml b/packages/CompanionDeviceManager/res/values-fi/strings.xml
index c8dbeb5..a1c15f1 100644
--- a/packages/CompanionDeviceManager/res/values-fi/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-fi/strings.xml
@@ -22,18 +22,30 @@
<string name="chooser_title" msgid="2262294130493605839">"Valitse <xliff:g id="PROFILE_NAME">%1$s</xliff:g>, jota <strong><xliff:g id="APP_NAME">%2$s</xliff:g></strong> hallinnoi"</string>
<string name="summary_watch" product="default" msgid="7113724443198337683">"<xliff:g id="APP_NAME">%1$s</xliff:g> saa luvan hallinnoida ilmoituksiasi sekä pääsyn puhelimeesi, tekstiviesteihisi, kontakteihisi ja kalenteriisi."</string>
<string name="summary_watch" product="tablet" msgid="7113724443198337683">"<xliff:g id="APP_NAME">%1$s</xliff:g> saa luvan hallinnoida ilmoituksiasi sekä pääsyn puhelimeesi, tekstiviesteihisi, kontakteihisi ja kalenteriisi."</string>
- <string name="title_app_streaming" msgid="4459136600249308574">"Saako <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> striimata sovelluksia?"</string>
+ <string name="permission_apps" msgid="6142133265286656158">"Sovellukset"</string>
+ <string name="permission_apps_summary" msgid="798718816711515431">"Striimaa puhelimen sovelluksia"</string>
+ <string name="title_app_streaming" msgid="2270331024626446950">"Salli, että <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> saa pääsyn näihin puhelimesi tietoihin"</string>
<string name="summary_app_streaming" product="default" msgid="6105916810614498138">"Salli, että <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong> voi saada sovellukselta (<strong><xliff:g id="APP_NAME">%1$s</xliff:g>) etäpääsyoikeuden tälle puhelimelle asennettuihin sovelluksiin, kun laitteet on yhdistetty."</string>
<string name="summary_app_streaming" product="tablet" msgid="2996373715966272792">"Salli, että <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong> voi saada sovellukselta (<strong><xliff:g id="APP_NAME">%1$s</xliff:g>) etäpääsyoikeuden tälle tabletille asennettuihin sovelluksiin, kun laitteet on yhdistetty."</string>
<string name="summary_app_streaming" product="device" msgid="7614171699434639963">"Salli, että <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong> voi saada sovellukselta (<strong><xliff:g id="APP_NAME">%1$s</xliff:g>) etäpääsyoikeuden tälle laitteelle asennettuihin sovelluksiin, kun laitteet on yhdistetty."</string>
+ <string name="helper_title_app_streaming" msgid="4151687003439969765">"Laitteidenväliset palvelut"</string>
+ <string name="helper_summary_app_streaming" msgid="5344341720432827388">"Palvelua käytetään sovellusten striimaukseen laitteiden välillä"</string>
<string name="title_automotive_projection" msgid="3296005598978412847"></string>
<string name="summary_automotive_projection" msgid="8683801274662496164"></string>
<string name="title_computer" msgid="4693714143506569253">"Salli pääsy tähän tietoon puhelimellasi: <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong>"</string>
<string name="summary_computer" msgid="3798467601598297062"></string>
+ <string name="permission_notification" msgid="693762568127741203">"Ilmoitukset"</string>
+ <string name="permission_notification_summary" msgid="4398672775023193663">"Voi lukea kaikkia ilmoituksia, kuten sopimuksiin, viesteihin ja kuviin liittyviä tietoja"</string>
+ <string name="permission_storage" msgid="6831099350839392343">"Kuvat ja media"</string>
+ <string name="permission_storage_summary" msgid="3918240895519506417"></string>
+ <string name="helper_title_computer" msgid="4671071173916176037">"Google Play Palvelut"</string>
+ <string name="helper_summary_computer" product="default" msgid="467996390095403648">"Palvelu jakaa kuvia, mediaa ja ilmoituksia puhelimelta muille laitteille"</string>
+ <string name="helper_summary_computer" product="tablet" msgid="467996390095403648">"Palvelu jakaa kuvia, mediaa ja ilmoituksia puhelimelta muille laitteille"</string>
<string name="profile_name_generic" msgid="6851028682723034988">"laite"</string>
<string name="summary_generic" msgid="2346762210105903720"></string>
<string name="consent_yes" msgid="8344487259618762872">"Salli"</string>
<string name="consent_no" msgid="2640796915611404382">"Älä salli"</string>
+ <string name="consent_ok" msgid="3662376764371001106">"OK"</string>
<string name="permission_sync_confirmation_title" msgid="667074294393493186">"Siirrä sovellusluvat kelloon"</string>
<string name="permission_sync_summary" msgid="8873391306499120778">"Sovellukset, jotka on asennettu kelloon käyttöönoton aikana, käyttävät samoja lupia kuin puhelin. Näin kello on helpompi ottaa käyttöön.\n\n Näihin lupiin saattaa kuulua pääsy kellon mikrofoniin ja sijaintiin."</string>
</resources>
diff --git a/packages/CompanionDeviceManager/res/values-fr-rCA/strings.xml b/packages/CompanionDeviceManager/res/values-fr-rCA/strings.xml
index 3d5898b..5bc0439 100644
--- a/packages/CompanionDeviceManager/res/values-fr-rCA/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-fr-rCA/strings.xml
@@ -22,18 +22,30 @@
<string name="chooser_title" msgid="2262294130493605839">"Choisissez un <xliff:g id="PROFILE_NAME">%1$s</xliff:g> qui sera géré par <strong><xliff:g id="APP_NAME">%2$s</xliff:g></strong>"</string>
<string name="summary_watch" product="default" msgid="7113724443198337683">"<xliff:g id="APP_NAME">%1$s</xliff:g> aura l\'autorisation d\'interagir avec vos notifications et d\'accéder aux autorisations pour votre téléphone, vos messages texte, vos contacts et votre agenda."</string>
<string name="summary_watch" product="tablet" msgid="7113724443198337683">"<xliff:g id="APP_NAME">%1$s</xliff:g> aura l\'autorisation d\'interagir avec vos notifications et d\'accéder aux autorisations pour votre téléphone, vos messages texte, vos contacts et votre agenda."</string>
- <string name="title_app_streaming" msgid="4459136600249308574">"Permettre à l\'application <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> de diffuser des applications?"</string>
+ <string name="permission_apps" msgid="6142133265286656158">"Applications"</string>
+ <string name="permission_apps_summary" msgid="798718816711515431">"Diffusez les applications de votre téléphone"</string>
+ <string name="title_app_streaming" msgid="2270331024626446950">"Autorisez <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> à accéder à ces informations à partir de votre téléphone"</string>
<string name="summary_app_streaming" product="default" msgid="6105916810614498138">"Permettez à l\'application <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> de donner à l\'appareil <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong> un accès à distance aux applications installées sur ce téléphone lorsqu\'il est connecté."</string>
<string name="summary_app_streaming" product="tablet" msgid="2996373715966272792">"Permettez à l\'application <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> de donner à l\'appareil <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong> un accès à distance aux applications installées sur cette tablette lorsqu\'elle est connectée."</string>
<string name="summary_app_streaming" product="device" msgid="7614171699434639963">"Permettez à l\'application <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> de donner à l\'appareil <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong> un accès à distance aux applications installées sur cet appareil lorsqu\'il est connecté."</string>
+ <string name="helper_title_app_streaming" msgid="4151687003439969765">"Services multiappareils"</string>
+ <string name="helper_summary_app_streaming" msgid="5344341720432827388">"Ce service est utilisé pour diffuser des applications entre vos appareils"</string>
<string name="title_automotive_projection" msgid="3296005598978412847"></string>
<string name="summary_automotive_projection" msgid="8683801274662496164"></string>
<string name="title_computer" msgid="4693714143506569253">"Autorisez <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> à accéder à ces informations à partir de votre téléphone"</string>
<string name="summary_computer" msgid="3798467601598297062"></string>
+ <string name="permission_notification" msgid="693762568127741203">"Notifications"</string>
+ <string name="permission_notification_summary" msgid="4398672775023193663">"Peut lire toutes les notifications, y compris les renseignements tels que les contacts, les messages et les photos"</string>
+ <string name="permission_storage" msgid="6831099350839392343">"Photos et fichiers multimédias"</string>
+ <string name="permission_storage_summary" msgid="3918240895519506417"></string>
+ <string name="helper_title_computer" msgid="4671071173916176037">"Services Google Play"</string>
+ <string name="helper_summary_computer" product="default" msgid="467996390095403648">"Ce service partage des photos, du contenu multimédia et des notifications à partir de votre téléphone vers d\'autres appareils"</string>
+ <string name="helper_summary_computer" product="tablet" msgid="467996390095403648">"Ce service partage des photos, du contenu multimédia et des notifications à partir de votre téléphone vers d\'autres appareils"</string>
<string name="profile_name_generic" msgid="6851028682723034988">"appareil"</string>
<string name="summary_generic" msgid="2346762210105903720"></string>
<string name="consent_yes" msgid="8344487259618762872">"Autoriser"</string>
<string name="consent_no" msgid="2640796915611404382">"Ne pas autoriser"</string>
+ <string name="consent_ok" msgid="3662376764371001106">"OK"</string>
<string name="permission_sync_confirmation_title" msgid="667074294393493186">"Transférer les autorisations de l\'application à votre montre"</string>
<string name="permission_sync_summary" msgid="8873391306499120778">"Pour faciliter la configuration de votre montre, les applications installées sur celle-ci reprennent les mêmes autorisations que celles installées sur votre téléphone.\n\n Ces autorisations peuvent comprendre l\'accès au microphone et à la position de votre montre."</string>
</resources>
diff --git a/packages/CompanionDeviceManager/res/values-fr/strings.xml b/packages/CompanionDeviceManager/res/values-fr/strings.xml
index ecd89aa..acf4cd6 100644
--- a/packages/CompanionDeviceManager/res/values-fr/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-fr/strings.xml
@@ -22,18 +22,30 @@
<string name="chooser_title" msgid="2262294130493605839">"Sélectionner le/la <xliff:g id="PROFILE_NAME">%1$s</xliff:g> qui sera géré(e) par <strong><xliff:g id="APP_NAME">%2$s</xliff:g></strong>"</string>
<string name="summary_watch" product="default" msgid="7113724443198337683">"<xliff:g id="APP_NAME">%1$s</xliff:g> aura l\'autorisation d\'interagir avec vos notifications et d\'accéder au téléphone, aux SMS, aux contacts et à l\'agenda."</string>
<string name="summary_watch" product="tablet" msgid="7113724443198337683">"<xliff:g id="APP_NAME">%1$s</xliff:g> aura l\'autorisation d\'interagir avec vos notifications et d\'accéder au téléphone, aux SMS, aux contacts et à l\'agenda."</string>
- <string name="title_app_streaming" msgid="4459136600249308574">"Autoriser <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> à diffuser des applis en streaming ?"</string>
+ <string name="permission_apps" msgid="6142133265286656158">"Applis"</string>
+ <string name="permission_apps_summary" msgid="798718816711515431">"Caster les applis de votre téléphone"</string>
+ <string name="title_app_streaming" msgid="2270331024626446950">"Autoriser <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> à accéder à ces informations depuis votre téléphone"</string>
<string name="summary_app_streaming" product="default" msgid="6105916810614498138">"Autoriser <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> à accéder à distance aux applis installées sur <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong> quand ce téléphone est connecté à Internet."</string>
<string name="summary_app_streaming" product="tablet" msgid="2996373715966272792">"Autoriser <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> à accéder à distance aux applis installées sur <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong> quand cette tablette est connectée à Internet."</string>
<string name="summary_app_streaming" product="device" msgid="7614171699434639963">"Autoriser <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> à accéder à distance aux applis installées sur <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong> quand cet appareil est connecté à Internet."</string>
+ <string name="helper_title_app_streaming" msgid="4151687003439969765">"Services inter-appareils"</string>
+ <string name="helper_summary_app_streaming" msgid="5344341720432827388">"Ce service est utilisé pour caster des applis d\'un appareil à l\'autre"</string>
<string name="title_automotive_projection" msgid="3296005598978412847"></string>
<string name="summary_automotive_projection" msgid="8683801274662496164"></string>
<string name="title_computer" msgid="4693714143506569253">"Autoriser <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> à accéder à ces informations depuis votre téléphone"</string>
<string name="summary_computer" msgid="3798467601598297062"></string>
+ <string name="permission_notification" msgid="693762568127741203">"Notifications"</string>
+ <string name="permission_notification_summary" msgid="4398672775023193663">"Peut lire toutes les notifications, y compris des informations, comme les contacts, messages et photos"</string>
+ <string name="permission_storage" msgid="6831099350839392343">"Photos et contenus multimédias"</string>
+ <string name="permission_storage_summary" msgid="3918240895519506417"></string>
+ <string name="helper_title_computer" msgid="4671071173916176037">"Services Google Play"</string>
+ <string name="helper_summary_computer" product="default" msgid="467996390095403648">"Ce service partage les photos, les contenus multimédias et les notifications de votre téléphone vers d\'autres appareils"</string>
+ <string name="helper_summary_computer" product="tablet" msgid="467996390095403648">"Ce service partage les photos, les contenus multimédias et les notifications de votre téléphone vers d\'autres appareils"</string>
<string name="profile_name_generic" msgid="6851028682723034988">"appareil"</string>
<string name="summary_generic" msgid="2346762210105903720"></string>
<string name="consent_yes" msgid="8344487259618762872">"Autoriser"</string>
<string name="consent_no" msgid="2640796915611404382">"Ne pas autoriser"</string>
+ <string name="consent_ok" msgid="3662376764371001106">"OK"</string>
<string name="permission_sync_confirmation_title" msgid="667074294393493186">"Transférer les autorisations de l\'appli vers la montre"</string>
<string name="permission_sync_summary" msgid="8873391306499120778">"Pour que votre montre soit plus facile à configurer, les applis qui y sont installées pendant la configuration utiliseront les mêmes autorisations que votre téléphone.\n\n Il peut s\'agir, par exemple, de l\'accès au micro et à la position de votre montre."</string>
</resources>
diff --git a/packages/CompanionDeviceManager/res/values-gl/strings.xml b/packages/CompanionDeviceManager/res/values-gl/strings.xml
index d060f29..d5f8515 100644
--- a/packages/CompanionDeviceManager/res/values-gl/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-gl/strings.xml
@@ -22,18 +22,30 @@
<string name="chooser_title" msgid="2262294130493605839">"Escolle un perfil (<xliff:g id="PROFILE_NAME">%1$s</xliff:g>) para que o xestione a aplicación <strong><xliff:g id="APP_NAME">%2$s</xliff:g></strong>"</string>
<string name="summary_watch" product="default" msgid="7113724443198337683">"<xliff:g id="APP_NAME">%1$s</xliff:g> poderá interactuar coas túas notificacións e acceder aos permisos do teu teléfono, das mensaxes, dos contactos e do calendario."</string>
<string name="summary_watch" product="tablet" msgid="7113724443198337683">"<xliff:g id="APP_NAME">%1$s</xliff:g> poderá interactuar coas túas notificacións e acceder aos permisos do teu teléfono, das mensaxes, dos contactos e do calendario."</string>
- <string name="title_app_streaming" msgid="4459136600249308574">"Queres permitir que <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> emita aplicacións noutros dispositivos?"</string>
+ <string name="permission_apps" msgid="6142133265286656158">"Aplicacións"</string>
+ <string name="permission_apps_summary" msgid="798718816711515431">"Emite as aplicacións do teu teléfono"</string>
+ <string name="title_app_streaming" msgid="2270331024626446950">"Permitir que a aplicación <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> acceda a esta información desde o teu teléfono"</string>
<string name="summary_app_streaming" product="default" msgid="6105916810614498138">"Permite que <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> lle outorgue a <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong> acceso remoto a aplicacións instaladas neste teléfono cando teña conexión a Internet."</string>
<string name="summary_app_streaming" product="tablet" msgid="2996373715966272792">"Permite que <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> lle outorgue a <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong> acceso remoto a aplicacións instaladas nesta tableta cando teña conexión a Internet."</string>
<string name="summary_app_streaming" product="device" msgid="7614171699434639963">"Permite que <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> lle outorgue a <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong> acceso remoto a aplicacións instaladas neste dispositivo cando teña conexión a Internet."</string>
+ <string name="helper_title_app_streaming" msgid="4151687003439969765">"Servizos multidispositivo"</string>
+ <string name="helper_summary_app_streaming" msgid="5344341720432827388">"Este servizo utilízase para reproducir aplicacións en tempo real entre os teus dispositivos"</string>
<string name="title_automotive_projection" msgid="3296005598978412847"></string>
<string name="summary_automotive_projection" msgid="8683801274662496164"></string>
<string name="title_computer" msgid="4693714143506569253">"Permitir que <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> acceda a esta información desde o teu teléfono"</string>
<string name="summary_computer" msgid="3798467601598297062"></string>
+ <string name="permission_notification" msgid="693762568127741203">"Notificacións"</string>
+ <string name="permission_notification_summary" msgid="4398672775023193663">"Pode ler todas as notificacións (que poden incluír información como contactos, mensaxes e fotos)"</string>
+ <string name="permission_storage" msgid="6831099350839392343">"Fotos e contido multimedia"</string>
+ <string name="permission_storage_summary" msgid="3918240895519506417"></string>
+ <string name="helper_title_computer" msgid="4671071173916176037">"Servizos de Google Play"</string>
+ <string name="helper_summary_computer" product="default" msgid="467996390095403648">"Este servizo comparte con outros dispositivos as fotos, o contido multimedia e as notificacións do teu teléfono"</string>
+ <string name="helper_summary_computer" product="tablet" msgid="467996390095403648">"Este servizo comparte con outros dispositivos as fotos, o contido multimedia e as notificacións do teu teléfono"</string>
<string name="profile_name_generic" msgid="6851028682723034988">"dispositivo"</string>
<string name="summary_generic" msgid="2346762210105903720"></string>
<string name="consent_yes" msgid="8344487259618762872">"Permitir"</string>
<string name="consent_no" msgid="2640796915611404382">"Non permitir"</string>
+ <string name="consent_ok" msgid="3662376764371001106">"Aceptar"</string>
<string name="permission_sync_confirmation_title" msgid="667074294393493186">"Transferir os permisos de aplicacións ao reloxo"</string>
<string name="permission_sync_summary" msgid="8873391306499120778">"Para que che resulte máis doado configurar o reloxo, as aplicacións que instales nel durante a configuración usarán os mesmos permisos que o teléfono.\n\n Entre estes permisos poden estar incluídos os de acceso ao micrófono e á localización do teléfono."</string>
</resources>
diff --git a/packages/CompanionDeviceManager/res/values-gu/strings.xml b/packages/CompanionDeviceManager/res/values-gu/strings.xml
index d06d8c6..adfc6a0 100644
--- a/packages/CompanionDeviceManager/res/values-gu/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-gu/strings.xml
@@ -22,18 +22,30 @@
<string name="chooser_title" msgid="2262294130493605839">"<strong><xliff:g id="APP_NAME">%2$s</xliff:g></strong> દ્વારા મેનેજ કરવા માટે કોઈ <xliff:g id="PROFILE_NAME">%1$s</xliff:g> પસંદ કરો"</string>
<string name="summary_watch" product="default" msgid="7113724443198337683">"<xliff:g id="APP_NAME">%1$s</xliff:g>ને તમારા નોટિફિકેશન સાથે ક્રિયાપ્રતિક્રિયા કરવાની તેમજ તમારો ફોન, SMS, સંપર્કો તેમજ કૅલેન્ડરની પરવાનગીઓ ઍક્સેસ કરવાની મંજૂરી આપવામાં આવશે."</string>
<string name="summary_watch" product="tablet" msgid="7113724443198337683">"<xliff:g id="APP_NAME">%1$s</xliff:g>ને તમારા નોટિફિકેશન સાથે ક્રિયાપ્રતિક્રિયા કરવાની તેમજ તમારો ફોન, SMS, સંપર્કો તેમજ કૅલેન્ડરની પરવાનગીઓ ઍક્સેસ કરવાની મંજૂરી આપવામાં આવશે."</string>
- <string name="title_app_streaming" msgid="4459136600249308574">"શું </strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong>ને ઍપ્લિકેશનો સ્ટ્રીમ કરવાની મંજૂરી આપીએ?"</string>
+ <string name="permission_apps" msgid="6142133265286656158">"ઍપ"</string>
+ <string name="permission_apps_summary" msgid="798718816711515431">"તમારા ફોનની ઍપ સ્ટ્રીમ કરો"</string>
+ <string name="title_app_streaming" msgid="2270331024626446950">"તમારા ફોનમાંથી આ માહિતી ઍક્સેસ કરવા માટે, <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong>ને મંજૂરી આપો"</string>
<string name="summary_app_streaming" product="default" msgid="6105916810614498138">"જ્યારે કનેક્ટ કરવામાં આવે, ત્યારે આ ફોન પર ઇન્સ્ટૉલ કરવામાં આવેલી ઍપ્લિકેશનોનો રિમોટ ઍક્સેસ <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong>ને <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong>ને પ્રદાન કરવા દો."</string>
<string name="summary_app_streaming" product="tablet" msgid="2996373715966272792">"જ્યારે કનેક્ટ કરવામાં આવે, ત્યારે આ ટૅબ્લેટ પર ઇન્સ્ટૉલ કરવામાં આવેલી ઍપ્લિકેશનોનો રિમોટ ઍક્સેસ <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong>ને <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong>ને પ્રદાન કરવા દો."</string>
<string name="summary_app_streaming" product="device" msgid="7614171699434639963">"જ્યારે કનેક્ટ કરવામાં આવે, ત્યારે આ ડિવાઇસ પર ઇન્સ્ટૉલ કરવામાં આવેલી ઍપ્લિકેશનોનો રિમોટ ઍક્સેસ <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong>ને <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong>ને પ્રદાન કરવા દો."</string>
+ <string name="helper_title_app_streaming" msgid="4151687003439969765">"ક્રોસ-ડિવાઇસ સેવાઓ"</string>
+ <string name="helper_summary_app_streaming" msgid="5344341720432827388">"આ સેવાનો ઉપયોગ તમારા ડિવાઇસ વચ્ચે ઍપ સ્ટ્રીમ કરવા માટે કરવામાં આવે છે"</string>
<string name="title_automotive_projection" msgid="3296005598978412847"></string>
<string name="summary_automotive_projection" msgid="8683801274662496164"></string>
<string name="title_computer" msgid="4693714143506569253">"તમારા ફોનમાંથી આ માહિતી ઍક્સેસ કરવા માટે, <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong>ને મંજૂરી આપો"</string>
<string name="summary_computer" msgid="3798467601598297062"></string>
+ <string name="permission_notification" msgid="693762568127741203">"નોટિફિકેશન"</string>
+ <string name="permission_notification_summary" msgid="4398672775023193663">"સંપર્કો, મેસેજ અને ફોટા જેવી માહિતી સહિતના બધા નોટિફિકેશન વાંચી શકે છે"</string>
+ <string name="permission_storage" msgid="6831099350839392343">"ફોટા અને મીડિયા"</string>
+ <string name="permission_storage_summary" msgid="3918240895519506417"></string>
+ <string name="helper_title_computer" msgid="4671071173916176037">"Google Play સેવાઓ"</string>
+ <string name="helper_summary_computer" product="default" msgid="467996390095403648">"આ સેવા ફોટા, મીડિયા અને નોટિફિકેશનને તમારા ફોન પરથી અન્ય ડિવાઇસ પર શેર કરે છે"</string>
+ <string name="helper_summary_computer" product="tablet" msgid="467996390095403648">"આ સેવા ફોટા, મીડિયા અને નોટિફિકેશનને તમારા ફોન પરથી અન્ય ડિવાઇસ પર શેર કરે છે"</string>
<string name="profile_name_generic" msgid="6851028682723034988">"ડિવાઇસ"</string>
<string name="summary_generic" msgid="2346762210105903720"></string>
<string name="consent_yes" msgid="8344487259618762872">"મંજૂરી આપો"</string>
<string name="consent_no" msgid="2640796915611404382">"મંજૂરી આપશો નહીં"</string>
+ <string name="consent_ok" msgid="3662376764371001106">"ઓકે"</string>
<string name="permission_sync_confirmation_title" msgid="667074294393493186">"તમારી ઘડિયાળમાં ઍપ પરવાનગીઓ ટ્રાન્સફર કરો"</string>
<string name="permission_sync_summary" msgid="8873391306499120778">"તમારી ઘડિયાળનું સેટઅપ કરવાનું સરળ બનાવવા માટે, સેટઅપ દરમિયાન તમારી ઘડિયાળ પર ઇન્સ્ટૉલ કરેલી ઍપ દ્વારા તમારા ફોન પર મળેલી પરવાનગીઓનો ઉપયોગ કરવામાં આવશે.\n\n આ પરવાનગીઓમાં તમારી ઘડિયાળના માઇક્રોફોન અને સ્થાન સંબંધિત માહિતીનો ઍક્સેસ શામેલ હોઈ શકે છે."</string>
</resources>
diff --git a/packages/CompanionDeviceManager/res/values-hi/strings.xml b/packages/CompanionDeviceManager/res/values-hi/strings.xml
index 1be6af8..71c5f12 100644
--- a/packages/CompanionDeviceManager/res/values-hi/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-hi/strings.xml
@@ -22,18 +22,30 @@
<string name="chooser_title" msgid="2262294130493605839">"कोई <xliff:g id="PROFILE_NAME">%1$s</xliff:g> चुनें, ताकि उसे <strong><xliff:g id="APP_NAME">%2$s</xliff:g></strong> की मदद से प्रबंधित किया जा सके"</string>
<string name="summary_watch" product="default" msgid="7113724443198337683">"<xliff:g id="APP_NAME">%1$s</xliff:g> आपकी सूचनाओं पर कार्रवाई कर पाएगा. साथ ही, यह आपके फ़ोन, एसएमएस, संपर्कों, और कैलेंडर की अनुमतियों को भी ऐक्सेस कर पाएगा."</string>
<string name="summary_watch" product="tablet" msgid="7113724443198337683">"<xliff:g id="APP_NAME">%1$s</xliff:g> आपकी सूचनाओं पर कार्रवाई कर पाएगा. साथ ही, यह आपके फ़ोन, एसएमएस, संपर्कों, और कैलेंडर की अनुमतियों को भी ऐक्सेस कर पाएगा."</string>
- <string name="title_app_streaming" msgid="4459136600249308574">"<strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> को ऐप्लिकेशन स्ट्रीम करने की अनुमति देनी है?"</string>
+ <string name="permission_apps" msgid="6142133265286656158">"ऐप्लिकेशन"</string>
+ <string name="permission_apps_summary" msgid="798718816711515431">"अपने फ़ोन के ऐप्लिकेशन को स्ट्रीम करें"</string>
+ <string name="title_app_streaming" msgid="2270331024626446950">"<strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> को अपने फ़ोन से यह जानकारी ऐक्सेस करने की अनुमति दें"</string>
<string name="summary_app_streaming" product="default" msgid="6105916810614498138">"कनेक्ट होने पर, <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> को <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong> के रिमोट ऐक्सेस की अनुमति दें, ताकि इस फ़ोन पर इंस्टॉल किए गए ऐप्लिकेशन ऐक्सेस किए जा सकें."</string>
<string name="summary_app_streaming" product="tablet" msgid="2996373715966272792">"कनेक्ट होने पर, <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> को <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong> के रिमोट ऐक्सेस की अनुमति दें, ताकि इस टैबलेट पर इंस्टॉल किए गए ऐप्लिकेशन ऐक्सेस किए जा सकें."</string>
<string name="summary_app_streaming" product="device" msgid="7614171699434639963">"कनेक्ट होने पर, <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> को <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong> के रिमोट ऐक्सेस की अनुमति दें, ताकि इस डिवाइस पर इंस्टॉल किए गए ऐप्लिकेशन ऐक्सेस किए जा सकें."</string>
+ <string name="helper_title_app_streaming" msgid="4151687003439969765">"क्रॉस-डिवाइस से जुड़ी सेवाएं"</string>
+ <string name="helper_summary_app_streaming" msgid="5344341720432827388">"इस सेवा का इस्तेमाल, आपके डिवाइसों के बीच ऐप्लिकेशन कास्ट करने के लिए किया जाता है"</string>
<string name="title_automotive_projection" msgid="3296005598978412847"></string>
<string name="summary_automotive_projection" msgid="8683801274662496164"></string>
<string name="title_computer" msgid="4693714143506569253">"<strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> को अपने फ़ोन से यह जानकारी ऐक्सेस करने की अनुमति दें"</string>
<string name="summary_computer" msgid="3798467601598297062"></string>
+ <string name="permission_notification" msgid="693762568127741203">"सूचनाएं"</string>
+ <string name="permission_notification_summary" msgid="4398672775023193663">"इससे सभी सूचनाएं देखी जा सकती हैं. इसमें संपर्क, मैसेज, और फ़ोटो जैसी जानकारी शामिल है"</string>
+ <string name="permission_storage" msgid="6831099350839392343">"फ़ोटो और मीडिया"</string>
+ <string name="permission_storage_summary" msgid="3918240895519506417"></string>
+ <string name="helper_title_computer" msgid="4671071173916176037">"Google Play सेवाएं"</string>
+ <string name="helper_summary_computer" product="default" msgid="467996390095403648">"इस सेवा की मदद से, आपके फ़ोन से फ़ोटो, मीडिया, और सूचनाओं को दूसरे डिवाइसों के साथ शेयर किया जाता है"</string>
+ <string name="helper_summary_computer" product="tablet" msgid="467996390095403648">"इस सेवा की मदद से, आपके फ़ोन से फ़ोटो, मीडिया, और सूचनाओं को दूसरे डिवाइसों के साथ शेयर किया जाता है"</string>
<string name="profile_name_generic" msgid="6851028682723034988">"डिवाइस"</string>
<string name="summary_generic" msgid="2346762210105903720"></string>
<string name="consent_yes" msgid="8344487259618762872">"अनुमति दें"</string>
<string name="consent_no" msgid="2640796915611404382">"अनुमति न दें"</string>
+ <string name="consent_ok" msgid="3662376764371001106">"ठीक है"</string>
<string name="permission_sync_confirmation_title" msgid="667074294393493186">"ऐप्लिकेशन से जुड़ी अनुमतियों को अपनी वॉच में ट्रांसफ़र करें"</string>
<string name="permission_sync_summary" msgid="8873391306499120778">"वॉच को सेट अप करने की प्रोसेस को आसान बनाने के लिए, उस पर इंस्टॉल किए गए ऐप्लिकेशन को भी वही अनुमतियां मिलेंगी जो आपने उन ऐप्लिकेशन को फ़ोन पर दी होंगी.\n\n इन अनुमतियों में, आपकी वॉच के माइक्रोफ़ोन और जगह की जानकारी का ऐक्सेस शामिल हो सकता है."</string>
</resources>
diff --git a/packages/CompanionDeviceManager/res/values-hr/strings.xml b/packages/CompanionDeviceManager/res/values-hr/strings.xml
index 610b7bd..fd7e302 100644
--- a/packages/CompanionDeviceManager/res/values-hr/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-hr/strings.xml
@@ -22,18 +22,30 @@
<string name="chooser_title" msgid="2262294130493605839">"Odaberite profil <xliff:g id="PROFILE_NAME">%1$s</xliff:g> kojim će upravljati aplikacija <strong><xliff:g id="APP_NAME">%2$s</xliff:g></strong>"</string>
<string name="summary_watch" product="default" msgid="7113724443198337683">"Aplikacija <xliff:g id="APP_NAME">%1$s</xliff:g> moći će stupati u interakciju s vašim obavijestima i pristupati dopuštenjima za telefon, SMS-ove, kontakte i kalendar."</string>
<string name="summary_watch" product="tablet" msgid="7113724443198337683">"Aplikacija <xliff:g id="APP_NAME">%1$s</xliff:g> moći će stupati u interakciju s vašim obavijestima i pristupati dopuštenjima za telefon, SMS-ove, kontakte i kalendar."</string>
- <string name="title_app_streaming" msgid="4459136600249308574">"Dopustiti aplikaciji <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> pokretanje streama aplikacija?"</string>
+ <string name="permission_apps" msgid="6142133265286656158">"Aplikacije"</string>
+ <string name="permission_apps_summary" msgid="798718816711515431">"Streaming aplikacija vašeg telefona"</string>
+ <string name="title_app_streaming" msgid="2270331024626446950">"Omogućite aplikaciji <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> da pristupa informacijama s vašeg telefona"</string>
<string name="summary_app_streaming" product="default" msgid="6105916810614498138">"Dopustite aplikaciji <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> da telefonu <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong> omogući udaljeni pristup aplikacijama koje su instalirane na tom telefonu kada su povezani."</string>
<string name="summary_app_streaming" product="tablet" msgid="2996373715966272792">"Dopustite aplikaciji <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> da tabletu <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong> omogući udaljeni pristup aplikacijama koje su instalirane na tom tabletu kada su povezani."</string>
<string name="summary_app_streaming" product="device" msgid="7614171699434639963">"Dopustite aplikaciji <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> da uređaju <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong> omogući udaljeni pristup aplikacijama koje su instalirane na tom uređaju kada su povezani."</string>
+ <string name="helper_title_app_streaming" msgid="4151687003439969765">"Usluge na različitim uređajima"</string>
+ <string name="helper_summary_app_streaming" msgid="5344341720432827388">"Ova se usluga koristi za streaming aplikacija između vaših uređaja"</string>
<string name="title_automotive_projection" msgid="3296005598978412847"></string>
<string name="summary_automotive_projection" msgid="8683801274662496164"></string>
<string name="title_computer" msgid="4693714143506569253">"Omogućite aplikaciji <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> da pristupa informacijama s vašeg telefona"</string>
<string name="summary_computer" msgid="3798467601598297062"></string>
+ <string name="permission_notification" msgid="693762568127741203">"Obavijesti"</string>
+ <string name="permission_notification_summary" msgid="4398672775023193663">"Može čitati sve obavijesti, uključujući informacije kao što su kontakti, poruke i fotografije"</string>
+ <string name="permission_storage" msgid="6831099350839392343">"Fotografije i mediji"</string>
+ <string name="permission_storage_summary" msgid="3918240895519506417"></string>
+ <string name="helper_title_computer" msgid="4671071173916176037">"Usluge za Google Play"</string>
+ <string name="helper_summary_computer" product="default" msgid="467996390095403648">"Ova usluga dijeli fotografije, medijske sadržaje i obavijesti s vašeg telefona na druge uređaje"</string>
+ <string name="helper_summary_computer" product="tablet" msgid="467996390095403648">"Ova usluga dijeli fotografije, medijske sadržaje i obavijesti s vašeg telefona na druge uređaje"</string>
<string name="profile_name_generic" msgid="6851028682723034988">"uređaj"</string>
<string name="summary_generic" msgid="2346762210105903720"></string>
<string name="consent_yes" msgid="8344487259618762872">"Dopusti"</string>
<string name="consent_no" msgid="2640796915611404382">"Nemoj dopustiti"</string>
+ <string name="consent_ok" msgid="3662376764371001106">"U redu"</string>
<string name="permission_sync_confirmation_title" msgid="667074294393493186">"Prijenos dopuštenja aplikacije na sat"</string>
<string name="permission_sync_summary" msgid="8873391306499120778">"Kako bi postavljanje sata bilo jednostavnije, aplikacije instalirane na satu će tijekom postavljanja upotrebljavati ista dopuštenja kao telefon.\n\n Ta dopuštenja mogu uključivati pristup mikrofonu i lokaciji sata."</string>
</resources>
diff --git a/packages/CompanionDeviceManager/res/values-hu/strings.xml b/packages/CompanionDeviceManager/res/values-hu/strings.xml
index 625a3e9..c9ef48a 100644
--- a/packages/CompanionDeviceManager/res/values-hu/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-hu/strings.xml
@@ -22,18 +22,30 @@
<string name="chooser_title" msgid="2262294130493605839">"A(z) <strong><xliff:g id="APP_NAME">%2$s</xliff:g></strong> alkalmazással kezelni kívánt <xliff:g id="PROFILE_NAME">%1$s</xliff:g> kiválasztása"</string>
<string name="summary_watch" product="default" msgid="7113724443198337683">"A(z) <xliff:g id="APP_NAME">%1$s</xliff:g> műveleteket végezhet majd az értesítésekkel, és hozzáférhet a telefonra, az SMS-ekre, a névjegyekre és a naptárra vonatkozó engedélyekhez."</string>
<string name="summary_watch" product="tablet" msgid="7113724443198337683">"A(z) <xliff:g id="APP_NAME">%1$s</xliff:g> műveleteket végezhet majd az értesítésekkel, és hozzáférhet a telefonra, az SMS-ekre, a névjegyekre és a naptárra vonatkozó engedélyekhez."</string>
- <string name="title_app_streaming" msgid="4459136600249308574">"Engedélyezi a(z) <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> alkalmazásnak appok streamelését?"</string>
+ <string name="permission_apps" msgid="6142133265286656158">"Alkalmazások"</string>
+ <string name="permission_apps_summary" msgid="798718816711515431">"A telefon alkalmazásainak streamelése"</string>
+ <string name="title_app_streaming" msgid="2270331024626446950">"Engedélyezi a(z) „<xliff:g id="APP_NAME">%1$s</xliff:g>” alkalmazás számára az információhoz való hozzáférést a telefonról"</string>
<string name="summary_app_streaming" product="default" msgid="6105916810614498138">"Engedélyezheti a(z) <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> alkalmazásnak, hogy a(z) <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong> eszköz számára távoli hozzáférést biztosítson a telefonra telepített alkalmazásokhoz, amikor a telefon csatlakoztatva van."</string>
<string name="summary_app_streaming" product="tablet" msgid="2996373715966272792">"Engedélyezheti a(z) <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> alkalmazásnak, hogy a(z) <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong> eszköz számára távoli hozzáférést biztosítson a táblagépre telepített alkalmazásokhoz, amikor a táblagép csatlakoztatva van."</string>
<string name="summary_app_streaming" product="device" msgid="7614171699434639963">"Engedélyezheti a(z) <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> alkalmazásnak, hogy a(z) <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong> eszköz számára távoli hozzáférést biztosítson az eszközre telepített alkalmazásokhoz, amikor az eszköz csatlakoztatva van."</string>
+ <string name="helper_title_app_streaming" msgid="4151687003439969765">"Többeszközös szolgáltatások"</string>
+ <string name="helper_summary_app_streaming" msgid="5344341720432827388">"Ez a szolgáltatás az eszközök közötti alkalmazásstreamelésre szolgál"</string>
<string name="title_automotive_projection" msgid="3296005598978412847"></string>
<string name="summary_automotive_projection" msgid="8683801274662496164"></string>
<string name="title_computer" msgid="4693714143506569253">"Engedélyezi a(z) „<xliff:g id="APP_NAME">%1$s</xliff:g>” alkalmazás számára az információhoz való hozzáférést a telefonról"</string>
<string name="summary_computer" msgid="3798467601598297062"></string>
+ <string name="permission_notification" msgid="693762568127741203">"Értesítések"</string>
+ <string name="permission_notification_summary" msgid="4398672775023193663">"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_storage" msgid="6831099350839392343">"Fotók és médiatartalmak"</string>
+ <string name="permission_storage_summary" msgid="3918240895519506417"></string>
+ <string name="helper_title_computer" msgid="4671071173916176037">"Google Play-szolgáltatások"</string>
+ <string name="helper_summary_computer" product="default" msgid="467996390095403648">"Ezzel a szolgáltatással fényképeket, médiatartalmakat és értesítéseket küldhet át a telefonjáról más eszközökre"</string>
+ <string name="helper_summary_computer" product="tablet" msgid="467996390095403648">"Ezzel a szolgáltatással fényképeket, médiatartalmakat és értesítéseket küldhet át a telefonjáról más eszközökre"</string>
<string name="profile_name_generic" msgid="6851028682723034988">"eszköz"</string>
<string name="summary_generic" msgid="2346762210105903720"></string>
<string name="consent_yes" msgid="8344487259618762872">"Engedélyezés"</string>
<string name="consent_no" msgid="2640796915611404382">"Tiltás"</string>
+ <string name="consent_ok" msgid="3662376764371001106">"OK"</string>
<string name="permission_sync_confirmation_title" msgid="667074294393493186">"Alkalmazásengedélyek átvitele az órára"</string>
<string name="permission_sync_summary" msgid="8873391306499120778">"Az óra beállításának megkönnyítése érdekében a beállítás során az órára telepített alkalmazások ugyanazokat az engedélyeket használják majd, mint a telefonja.\n\n Ezek az engedélyek magukban foglalhatják az óra mikrofonjához és helyadataihoz való hozzáférést."</string>
</resources>
diff --git a/packages/CompanionDeviceManager/res/values-hy/strings.xml b/packages/CompanionDeviceManager/res/values-hy/strings.xml
index f09441f..77c8bef 100644
--- a/packages/CompanionDeviceManager/res/values-hy/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-hy/strings.xml
@@ -22,18 +22,30 @@
<string name="chooser_title" msgid="2262294130493605839">"Ընտրեք <xliff:g id="PROFILE_NAME">%1$s</xliff:g>ը, որը պետք է կառավարվի <strong><xliff:g id="APP_NAME">%2$s</xliff:g></strong> հավելվածի կողմից"</string>
<string name="summary_watch" product="default" msgid="7113724443198337683">"<xliff:g id="APP_NAME">%1$s</xliff:g> հավելվածը կկարողանա փոխազդել ձեր ծանուցումների հետ և կստանա «Հեռախոս», «SMS», «Կոնտակտներ» և «Օրացույց» ծառայությունների թույլտվությունները։"</string>
<string name="summary_watch" product="tablet" msgid="7113724443198337683">"<xliff:g id="APP_NAME">%1$s</xliff:g> հավելվածը կկարողանա փոխազդել ձեր ծանուցումների հետ և կստանա «Հեռախոս», «SMS», «Կոնտակտներ» և «Օրացույց» ծառայությունների թույլտվությունները։"</string>
- <string name="title_app_streaming" msgid="4459136600249308574">"Թույլատրե՞լ <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> հավելվածին բացել հավելվածներ"</string>
+ <string name="permission_apps" msgid="6142133265286656158">"Հավելվածներ"</string>
+ <string name="permission_apps_summary" msgid="798718816711515431">"Հեռարձակել հեռախոսի հավելվածները"</string>
+ <string name="title_app_streaming" msgid="2270331024626446950">"Թույլատրեք <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> հավելվածին օգտագործել այս տեղեկությունները ձեր հեռախոսից"</string>
<string name="summary_app_streaming" product="default" msgid="6105916810614498138">"Թույլ տվեք, որ <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> հավելվածը կապի հաստատման դեպքում <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong>-ին տրամադրի այս հեռախոսում տեղադրված հավելվածներ հեռակա մուտք գործելու թույլտվություն։"</string>
<string name="summary_app_streaming" product="tablet" msgid="2996373715966272792">"Թույլ տվեք, որ <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> հավելվածը կապի հաստատման դեպքում <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong>-ին տրամադրի այս պլանշետում տեղադրված հավելվածներ հեռակա մուտք գործելու թույլտվություն։"</string>
<string name="summary_app_streaming" product="device" msgid="7614171699434639963">"Թույլ տվեք, որ <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> հավելվածը ինտերնետ կապի հաստատման դեպքում <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong>-ին տրամադրի այս սարքում տեղադրված հավելվածներ հեռակա մուտք գործելու թույլտվություն։"</string>
+ <string name="helper_title_app_streaming" msgid="4151687003439969765">"Միջսարքային ծառայություններ"</string>
+ <string name="helper_summary_app_streaming" msgid="5344341720432827388">"Այս ծառայությունն օգտագործվում է ձեր սարքերի միջև հավելվածներ հեռարձակելու համար"</string>
<string name="title_automotive_projection" msgid="3296005598978412847"></string>
<string name="summary_automotive_projection" msgid="8683801274662496164"></string>
<string name="title_computer" msgid="4693714143506569253">"Թույլատրեք <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> հավելվածին օգտագործել այս տեղեկությունները ձեր հեռախոսից"</string>
<string name="summary_computer" msgid="3798467601598297062"></string>
+ <string name="permission_notification" msgid="693762568127741203">"Ծանուցումներ"</string>
+ <string name="permission_notification_summary" msgid="4398672775023193663">"Կարող է կարդալ բոլոր ծանուցումները, ներառյալ տեղեկությունները, օրինակ՝ կոնտակտները, հաղորդագրությունները և լուսանկարները"</string>
+ <string name="permission_storage" msgid="6831099350839392343">"Լուսանկարներ և մուլտիմեդիա"</string>
+ <string name="permission_storage_summary" msgid="3918240895519506417"></string>
+ <string name="helper_title_computer" msgid="4671071173916176037">"Google Play ծառայություններ"</string>
+ <string name="helper_summary_computer" product="default" msgid="467996390095403648">"Այս ծառայությունը ձեր հեռախոսից լուսանկարներ, մեդիա ֆայլեր և ծանուցումներ է ուղարկում այլ սարքերի"</string>
+ <string name="helper_summary_computer" product="tablet" msgid="467996390095403648">"Այս ծառայությունը ձեր հեռախոսից լուսանկարներ, մեդիա ֆայլեր և ծանուցումներ է ուղարկում այլ սարքերի"</string>
<string name="profile_name_generic" msgid="6851028682723034988">"սարք"</string>
<string name="summary_generic" msgid="2346762210105903720"></string>
<string name="consent_yes" msgid="8344487259618762872">"Թույլատրել"</string>
<string name="consent_no" msgid="2640796915611404382">"Չթույլատրել"</string>
+ <string name="consent_ok" msgid="3662376764371001106">"Եղավ"</string>
<string name="permission_sync_confirmation_title" msgid="667074294393493186">"Հավելվածների թույլտվությունների տեղափոխում ժամացույց"</string>
<string name="permission_sync_summary" msgid="8873391306499120778">"Կարգավորման ժամանակ ժամացույցում տեղադրված հավելվածների համար կօգտագործվեն նույն թույլտվությունները, ինչ հեռախոսում։\n\n Այդ թույլտվությունները կարող են ներառել ժամացույցի խոսափողի կամ տեղադրության տվյալների օգտագործումը։"</string>
</resources>
diff --git a/packages/CompanionDeviceManager/res/values-in/strings.xml b/packages/CompanionDeviceManager/res/values-in/strings.xml
index ef52808..ff4363c 100644
--- a/packages/CompanionDeviceManager/res/values-in/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-in/strings.xml
@@ -22,18 +22,30 @@
<string name="chooser_title" msgid="2262294130493605839">"Pilih <xliff:g id="PROFILE_NAME">%1$s</xliff:g> untuk dikelola oleh <strong><xliff:g id="APP_NAME">%2$s</xliff:g></strong>"</string>
<string name="summary_watch" product="default" msgid="7113724443198337683">"<xliff:g id="APP_NAME">%1$s</xliff:g> akan diizinkan berinteraksi dengan notifikasi dan mengakses izin Telepon, SMS, Kontak, dan Kalender."</string>
<string name="summary_watch" product="tablet" msgid="7113724443198337683">"<xliff:g id="APP_NAME">%1$s</xliff:g> akan diizinkan berinteraksi dengan notifikasi dan mengakses izin Telepon, SMS, Kontak, dan Kalender."</string>
- <string name="title_app_streaming" msgid="4459136600249308574">"Izinkan <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> men-streaming aplikasi?"</string>
+ <string name="permission_apps" msgid="6142133265286656158">"Aplikasi"</string>
+ <string name="permission_apps_summary" msgid="798718816711515431">"Melakukan streaming aplikasi ponsel Anda"</string>
+ <string name="title_app_streaming" msgid="2270331024626446950">"Izinkan <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> untuk mengakses informasi ini dari ponsel Anda"</string>
<string name="summary_app_streaming" product="default" msgid="6105916810614498138">"Izinkan <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> memberikan akses jarak jauh ke <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong> guna mengakses aplikasi yang diinstal di ponsel ini saat terhubung."</string>
<string name="summary_app_streaming" product="tablet" msgid="2996373715966272792">"Izinkan <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> memberikan akses jarak jauh ke <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong> guna mengakses aplikasi yang diinstal di tablet ini saat terhubung."</string>
<string name="summary_app_streaming" product="device" msgid="7614171699434639963">"Izinkan <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> memberikan akses jarak jauh ke <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong> guna mengakses aplikasi yang diinstal di perangkat ini saat terhubung."</string>
+ <string name="helper_title_app_streaming" msgid="4151687003439969765">"Layanan lintas perangkat"</string>
+ <string name="helper_summary_app_streaming" msgid="5344341720432827388">"Layanan ini digunakan untuk menstreaming aplikasi antar-perangkat"</string>
<string name="title_automotive_projection" msgid="3296005598978412847"></string>
<string name="summary_automotive_projection" msgid="8683801274662496164"></string>
<string name="title_computer" msgid="4693714143506569253">"Izinkan <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> mengakses informasi ini dari ponsel Anda"</string>
<string name="summary_computer" msgid="3798467601598297062"></string>
+ <string name="permission_notification" msgid="693762568127741203">"Notifikasi"</string>
+ <string name="permission_notification_summary" msgid="4398672775023193663">"Dapat membaca semua notifikasi, termasuk informasi seperti kontak, pesan, dan foto"</string>
+ <string name="permission_storage" msgid="6831099350839392343">"Foto dan media"</string>
+ <string name="permission_storage_summary" msgid="3918240895519506417"></string>
+ <string name="helper_title_computer" msgid="4671071173916176037">"Layanan Google Play"</string>
+ <string name="helper_summary_computer" product="default" msgid="467996390095403648">"Layanan ini membagikan foto, media, dan notifikasi dari ponsel Anda ke perangkat lain"</string>
+ <string name="helper_summary_computer" product="tablet" msgid="467996390095403648">"Layanan ini membagikan foto, media, dan notifikasi dari ponsel Anda ke perangkat lain"</string>
<string name="profile_name_generic" msgid="6851028682723034988">"perangkat"</string>
<string name="summary_generic" msgid="2346762210105903720"></string>
<string name="consent_yes" msgid="8344487259618762872">"Izinkan"</string>
<string name="consent_no" msgid="2640796915611404382">"Jangan izinkan"</string>
+ <string name="consent_ok" msgid="3662376764371001106">"Oke"</string>
<string name="permission_sync_confirmation_title" msgid="667074294393493186">"Transfer izin aplikasi ke smartwatch"</string>
<string name="permission_sync_summary" msgid="8873391306499120778">"Untuk mempermudah penyiapan smartwatch, aplikasi yang diinstal di smartwatch selama penyiapan akan menggunakan izin yang sama dengan ponsel.\n\n Izin ini dapat meliputi akses ke mikrofon dan lokasi smartwatch."</string>
</resources>
diff --git a/packages/CompanionDeviceManager/res/values-is/strings.xml b/packages/CompanionDeviceManager/res/values-is/strings.xml
index c0ca2fcf3..b8646c7 100644
--- a/packages/CompanionDeviceManager/res/values-is/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-is/strings.xml
@@ -22,18 +22,30 @@
<string name="chooser_title" msgid="2262294130493605839">"Velja <xliff:g id="PROFILE_NAME">%1$s</xliff:g> sem <strong><xliff:g id="APP_NAME">%2$s</xliff:g></strong> á að stjórna"</string>
<string name="summary_watch" product="default" msgid="7113724443198337683">"<xliff:g id="APP_NAME">%1$s</xliff:g> fær aðgang að tilkynningum og heimildum síma, SMS, tengiliða og dagatals."</string>
<string name="summary_watch" product="tablet" msgid="7113724443198337683">"<xliff:g id="APP_NAME">%1$s</xliff:g> fær aðgang að tilkynningum og heimildum síma, SMS, tengiliða og dagatals."</string>
- <string name="title_app_streaming" msgid="4459136600249308574">"Leyfa <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> að streyma forritum?"</string>
+ <string name="permission_apps" msgid="6142133265286656158">"Forrit"</string>
+ <string name="permission_apps_summary" msgid="798718816711515431">"Streymdu forritum símans"</string>
+ <string name="title_app_streaming" msgid="2270331024626446950">"Veita <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> aðgang að þessum upplýsingum úr símanum þínum"</string>
<string name="summary_app_streaming" product="default" msgid="6105916810614498138">"Leyfa <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> að veita <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong> fjaraðgang að forritum sem eru sett upp í þessum síma þegar tenging er á."</string>
<string name="summary_app_streaming" product="tablet" msgid="2996373715966272792">"Leyfa <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> að veita <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong> fjaraðgang að forritum sem eru sett upp í þessari spjaldtölvu þegar tenging er á."</string>
<string name="summary_app_streaming" product="device" msgid="7614171699434639963">"Leyfa <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> að veita <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong> fjaraðgang að forritum sem eru sett upp í þessu tæki þegar tenging er á."</string>
+ <string name="helper_title_app_streaming" msgid="4151687003439969765">"Þjónustur á milli tækja"</string>
+ <string name="helper_summary_app_streaming" msgid="5344341720432827388">"Þessi þjónusta er notuð til að streyma forritum á milli tækjanna þinna"</string>
<string name="title_automotive_projection" msgid="3296005598978412847"></string>
<string name="summary_automotive_projection" msgid="8683801274662496164"></string>
<string name="title_computer" msgid="4693714143506569253">"Veita <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> aðgang að þessum upplýsingum úr símanum þínum"</string>
<string name="summary_computer" msgid="3798467601598297062"></string>
+ <string name="permission_notification" msgid="693762568127741203">"Tilkynningar"</string>
+ <string name="permission_notification_summary" msgid="4398672775023193663">"Getur lesið allar tilkynningar, þar á meðal upplýsingar á borð við samninga, skilaboð og myndir"</string>
+ <string name="permission_storage" msgid="6831099350839392343">"Myndir og efni"</string>
+ <string name="permission_storage_summary" msgid="3918240895519506417"></string>
+ <string name="helper_title_computer" msgid="4671071173916176037">"Þjónusta Google Play"</string>
+ <string name="helper_summary_computer" product="default" msgid="467996390095403648">"Þessi þjónusta deilir myndum, margmiðlunarefni og tilkynningum úr símanum yfir í önnur tæki"</string>
+ <string name="helper_summary_computer" product="tablet" msgid="467996390095403648">"Þessi þjónusta deilir myndum, margmiðlunarefni og tilkynningum úr símanum yfir í önnur tæki"</string>
<string name="profile_name_generic" msgid="6851028682723034988">"tæki"</string>
<string name="summary_generic" msgid="2346762210105903720"></string>
<string name="consent_yes" msgid="8344487259618762872">"Leyfa"</string>
<string name="consent_no" msgid="2640796915611404382">"Ekki leyfa"</string>
+ <string name="consent_ok" msgid="3662376764371001106">"Í lagi"</string>
<string name="permission_sync_confirmation_title" msgid="667074294393493186">"Flytja heimildir forrita yfir í úrið"</string>
<string name="permission_sync_summary" msgid="8873391306499120778">"Til að auðvelda uppsetningu úrsins munu forrit sem eru sett upp í úrinu við uppsetningu nota sömu heimildir og stilltar eru í símanum.\n\n Þessar heimildir kunna að fela í sér aðgang að hljóðnema og staðsetningu úrsins."</string>
</resources>
diff --git a/packages/CompanionDeviceManager/res/values-it/strings.xml b/packages/CompanionDeviceManager/res/values-it/strings.xml
index 5f88b7a..4dfb69b 100644
--- a/packages/CompanionDeviceManager/res/values-it/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-it/strings.xml
@@ -22,18 +22,30 @@
<string name="chooser_title" msgid="2262294130493605839">"Scegli un <xliff:g id="PROFILE_NAME">%1$s</xliff:g> che sia gestito da <strong><xliff:g id="APP_NAME">%2$s</xliff:g></strong>"</string>
<string name="summary_watch" product="default" msgid="7113724443198337683">"L\'app <xliff:g id="APP_NAME">%1$s</xliff:g> potrà interagire con le tue notifiche e accedere alle autorizzazioni Telefono, SMS, Contatti e Calendario."</string>
<string name="summary_watch" product="tablet" msgid="7113724443198337683">"L\'app <xliff:g id="APP_NAME">%1$s</xliff:g> potrà interagire con le tue notifiche e accedere alle autorizzazioni Telefono, SMS, Contatti e Calendario."</string>
- <string name="title_app_streaming" msgid="4459136600249308574">"Vuoi consentire all\'app <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> di riprodurre applicazioni in streaming?"</string>
+ <string name="permission_apps" msgid="6142133265286656158">"App"</string>
+ <string name="permission_apps_summary" msgid="798718816711515431">"Trasmetti in streaming le app del tuo telefono"</string>
+ <string name="title_app_streaming" msgid="2270331024626446950">"Consenti all\'app <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> di accedere a queste informazioni dal tuo telefono"</string>
<string name="summary_app_streaming" product="default" msgid="6105916810614498138">"Consenti all\'app <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> di fornire l\'accesso remoto a <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong> per accedere alle applicazioni installate su questo telefono quando è connesso."</string>
<string name="summary_app_streaming" product="tablet" msgid="2996373715966272792">"Consenti all\'app <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> di fornire l\'accesso remoto a <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong> per accedere alle applicazioni installate su questo tablet quando è connesso."</string>
<string name="summary_app_streaming" product="device" msgid="7614171699434639963">"Consenti all\'app <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> di fornire l\'accesso remoto a <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong> per accedere alle applicazioni installate su questo dispositivo quando è connesso."</string>
+ <string name="helper_title_app_streaming" msgid="4151687003439969765">"Servizi cross-device"</string>
+ <string name="helper_summary_app_streaming" msgid="5344341720432827388">"Questo servizio viene utilizzato per trasmettere in streaming le app tra i dispositivi"</string>
<string name="title_automotive_projection" msgid="3296005598978412847"></string>
<string name="summary_automotive_projection" msgid="8683801274662496164"></string>
<string name="title_computer" msgid="4693714143506569253">"Consenti a <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> di accedere a questa informazione dal tuo telefono"</string>
<string name="summary_computer" msgid="3798467601598297062"></string>
+ <string name="permission_notification" msgid="693762568127741203">"Notifiche"</string>
+ <string name="permission_notification_summary" msgid="4398672775023193663">"Puoi leggere tutte le notifiche, incluse le informazioni come contatti, messaggi e foto"</string>
+ <string name="permission_storage" msgid="6831099350839392343">"Foto e contenuti multimediali"</string>
+ <string name="permission_storage_summary" msgid="3918240895519506417"></string>
+ <string name="helper_title_computer" msgid="4671071173916176037">"Google Play Services"</string>
+ <string name="helper_summary_computer" product="default" msgid="467996390095403648">"Questo servizio condivide foto, contenuti multimediali e notifiche del telefono con altri dispositivi"</string>
+ <string name="helper_summary_computer" product="tablet" msgid="467996390095403648">"Questo servizio condivide foto, contenuti multimediali e notifiche del telefono con altri dispositivi"</string>
<string name="profile_name_generic" msgid="6851028682723034988">"dispositivo"</string>
<string name="summary_generic" msgid="2346762210105903720"></string>
<string name="consent_yes" msgid="8344487259618762872">"Consenti"</string>
<string name="consent_no" msgid="2640796915611404382">"Non consentire"</string>
+ <string name="consent_ok" msgid="3662376764371001106">"OK"</string>
<string name="permission_sync_confirmation_title" msgid="667074294393493186">"Trasferisci le autorizzazioni app all\'orologio"</string>
<string name="permission_sync_summary" msgid="8873391306499120778">"Per facilitare la configurazione dell\'orologio, le app installate su quest\'ultimo durante la configurazione useranno le stesse autorizzazioni delle app sul telefono.\n\n Queste autorizzazioni potrebbero includere l\'accesso al microfono e alla posizione dell\'orologio."</string>
</resources>
diff --git a/packages/CompanionDeviceManager/res/values-iw/strings.xml b/packages/CompanionDeviceManager/res/values-iw/strings.xml
index 4a811f0..a6373c1 100644
--- a/packages/CompanionDeviceManager/res/values-iw/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-iw/strings.xml
@@ -22,18 +22,30 @@
<string name="chooser_title" msgid="2262294130493605839">"בחירת <xliff:g id="PROFILE_NAME">%1$s</xliff:g> לניהול באמצעות <strong><xliff:g id="APP_NAME">%2$s</xliff:g></strong>"</string>
<string name="summary_watch" product="default" msgid="7113724443198337683">"האפליקציה <xliff:g id="APP_NAME">%1$s</xliff:g> תוכל לבצע פעולות בהתראות ותקבל הרשאות גישה לטלפון, ל-SMS לאנשי הקשר וליומן."</string>
<string name="summary_watch" product="tablet" msgid="7113724443198337683">"האפליקציה <xliff:g id="APP_NAME">%1$s</xliff:g> תוכל לבצע פעולות בהתראות ותקבל הרשאות גישה לטלפון, ל-SMS לאנשי הקשר וליומן."</string>
- <string name="title_app_streaming" msgid="4459136600249308574">"לאפשר לאפליקציה <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> לשדר אפליקציות?"</string>
+ <string name="permission_apps" msgid="6142133265286656158">"אפליקציות"</string>
+ <string name="permission_apps_summary" msgid="798718816711515431">"שידור אפליקציות מהטלפון"</string>
+ <string name="title_app_streaming" msgid="2270331024626446950">"מתן אישור לאפליקציה <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> לגשת למידע הזה מהטלפון שלך"</string>
<string name="summary_app_streaming" product="default" msgid="6105916810614498138">"האפליקציה <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> יכולה לספק ל-<strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong> גישה מרחוק כדי לגשת לאפליקציות שמותקנות בטלפון הזה כשיש חיבור."</string>
<string name="summary_app_streaming" product="tablet" msgid="2996373715966272792">"האפליקציה <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> יכולה לספק ל-<strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong> גישה מרחוק כדי לגשת לאפליקציות שמותקנות בטאבלט הזה כשיש חיבור."</string>
<string name="summary_app_streaming" product="device" msgid="7614171699434639963">"האפליקציה <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> יכולה לספק למכשיר <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong> גישה מרחוק כדי לגשת לאפליקציות שמותקנות במכשיר הזה כשיש חיבור."</string>
+ <string name="helper_title_app_streaming" msgid="4151687003439969765">"שירותים למספר מכשירים"</string>
+ <string name="helper_summary_app_streaming" msgid="5344341720432827388">"השירות הזה משמש לשידור אפליקציות בין המכשירים שברשותך"</string>
<string name="title_automotive_projection" msgid="3296005598978412847"></string>
<string name="summary_automotive_projection" msgid="8683801274662496164"></string>
<string name="title_computer" msgid="4693714143506569253">"מתן אישור לאפליקציה <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> לגשת למידע הזה מהטלפון שלך"</string>
<string name="summary_computer" msgid="3798467601598297062"></string>
+ <string name="permission_notification" msgid="693762568127741203">"התראות"</string>
+ <string name="permission_notification_summary" msgid="4398672775023193663">"גישה לכל ההתראות, כולל מידע כמו אנשי קשר, הודעות ותמונות"</string>
+ <string name="permission_storage" msgid="6831099350839392343">"תמונות ומדיה"</string>
+ <string name="permission_storage_summary" msgid="3918240895519506417"></string>
+ <string name="helper_title_computer" msgid="4671071173916176037">"Google Play Services"</string>
+ <string name="helper_summary_computer" product="default" msgid="467996390095403648">"השירות הזה משמש לשיתוף של תמונות, מדיה והתראות מהטלפון שלך עם מכשירים אחרים"</string>
+ <string name="helper_summary_computer" product="tablet" msgid="467996390095403648">"השירות הזה משמש לשיתוף של תמונות, מדיה והתראות מהטלפון שלך עם מכשירים אחרים"</string>
<string name="profile_name_generic" msgid="6851028682723034988">"מכשיר"</string>
<string name="summary_generic" msgid="2346762210105903720"></string>
<string name="consent_yes" msgid="8344487259618762872">"יש אישור"</string>
<string name="consent_no" msgid="2640796915611404382">"אין אישור"</string>
+ <string name="consent_ok" msgid="3662376764371001106">"אישור"</string>
<string name="permission_sync_confirmation_title" msgid="667074294393493186">"העברת ההרשאות הניתנות לאפליקציות אל השעון שלך"</string>
<string name="permission_sync_summary" msgid="8873391306499120778">"כדי לפשט את הגדרת השעון, אפליקציות שמותקנות במהלך ההגדרה יקבלו את אותן הרשאות שניתנו בטלפון.\n\n ההרשאות האלה עשויות לכלול גישה למיקרופון ולמיקום של השעון."</string>
</resources>
diff --git a/packages/CompanionDeviceManager/res/values-ja/strings.xml b/packages/CompanionDeviceManager/res/values-ja/strings.xml
index 5e8d544..392ca0a 100644
--- a/packages/CompanionDeviceManager/res/values-ja/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-ja/strings.xml
@@ -22,18 +22,30 @@
<string name="chooser_title" msgid="2262294130493605839">"<strong><xliff:g id="APP_NAME">%2$s</xliff:g></strong> の管理対象となる<xliff:g id="PROFILE_NAME">%1$s</xliff:g>の選択"</string>
<string name="summary_watch" product="default" msgid="7113724443198337683">"<xliff:g id="APP_NAME">%1$s</xliff:g> は通知を使用でき、電話、SMS、連絡先、カレンダーの権限にもアクセスできるようになります。"</string>
<string name="summary_watch" product="tablet" msgid="7113724443198337683">"<xliff:g id="APP_NAME">%1$s</xliff:g> は通知を使用でき、電話、SMS、連絡先、カレンダーの権限にもアクセスできるようになります。"</string>
- <string name="title_app_streaming" msgid="4459136600249308574">"<strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> にアプリのストリーミングを許可しますか?"</string>
+ <string name="permission_apps" msgid="6142133265286656158">"アプリ"</string>
+ <string name="permission_apps_summary" msgid="798718816711515431">"スマートフォンのアプリのストリーミング"</string>
+ <string name="title_app_streaming" msgid="2270331024626446950">"スマートフォンのこの情報へのアクセスを <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> に許可"</string>
<string name="summary_app_streaming" product="default" msgid="6105916810614498138">"インターネット接続時に <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong> がスマートフォン内にインストールされているアプリにリモートでアクセスすることを <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> に許可します。"</string>
<string name="summary_app_streaming" product="tablet" msgid="2996373715966272792">"インターネット接続時に <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong> がタブレット内にインストールされているアプリにリモートでアクセスすることを <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> に許可します。"</string>
<string name="summary_app_streaming" product="device" msgid="7614171699434639963">"インターネット接続時に <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong> がデバイス内にインストールされているアプリにリモートでアクセスすることを <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> に許可します。"</string>
+ <string name="helper_title_app_streaming" msgid="4151687003439969765">"クロスデバイス サービス"</string>
+ <string name="helper_summary_app_streaming" msgid="5344341720432827388">"本サービスは、デバイス間でのアプリのストリーミングに使用されます"</string>
<string name="title_automotive_projection" msgid="3296005598978412847"></string>
<string name="summary_automotive_projection" msgid="8683801274662496164"></string>
<string name="title_computer" msgid="4693714143506569253">"このスマートフォンからの情報へのアクセスを <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> に許可"</string>
<string name="summary_computer" msgid="3798467601598297062"></string>
+ <string name="permission_notification" msgid="693762568127741203">"通知"</string>
+ <string name="permission_notification_summary" msgid="4398672775023193663">"連絡先、メッセージ、写真に関する情報を含め、すべての通知を読み取ることができます"</string>
+ <string name="permission_storage" msgid="6831099350839392343">"写真とメディア"</string>
+ <string name="permission_storage_summary" msgid="3918240895519506417"></string>
+ <string name="helper_title_computer" msgid="4671071173916176037">"Google Play 開発者サービス"</string>
+ <string name="helper_summary_computer" product="default" msgid="467996390095403648">"本サービスは、スマートフォンから他のデバイスに写真、メディア、通知を共有します"</string>
+ <string name="helper_summary_computer" product="tablet" msgid="467996390095403648">"本サービスは、スマートフォンから他のデバイスに写真、メディア、通知を共有します"</string>
<string name="profile_name_generic" msgid="6851028682723034988">"デバイス"</string>
<string name="summary_generic" msgid="2346762210105903720"></string>
<string name="consent_yes" msgid="8344487259618762872">"許可"</string>
<string name="consent_no" msgid="2640796915611404382">"許可しない"</string>
+ <string name="consent_ok" msgid="3662376764371001106">"OK"</string>
<string name="permission_sync_confirmation_title" msgid="667074294393493186">"スマートウォッチへのアプリの権限の移行"</string>
<string name="permission_sync_summary" msgid="8873391306499120778">"スマートウォッチのセットアップを簡単にするため、セットアップ時にスマートウォッチにインストールされたアプリに、スマートフォンと同じ権限が適用されます。\n\n これらの権限には、スマートウォッチのマイクや位置情報へのアクセス権も含まれることがあります。"</string>
</resources>
diff --git a/packages/CompanionDeviceManager/res/values-ka/strings.xml b/packages/CompanionDeviceManager/res/values-ka/strings.xml
index 3b179bf..f057b8b 100644
--- a/packages/CompanionDeviceManager/res/values-ka/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-ka/strings.xml
@@ -22,18 +22,30 @@
<string name="chooser_title" msgid="2262294130493605839">"აირჩიეთ <xliff:g id="PROFILE_NAME">%1$s</xliff:g>, რომელიც უნდა მართოს <strong><xliff:g id="APP_NAME">%2$s</xliff:g></strong>-მა"</string>
<string name="summary_watch" product="default" msgid="7113724443198337683">"<xliff:g id="APP_NAME">%1$s</xliff:g> შეძლებს თქვენს შეტყობინებებთან ინტერაქციას და თქვენი ტელეფონის, SMS-ების, კონტაქტებისა და კალენდრის ნებართვებზე წვდომას."</string>
<string name="summary_watch" product="tablet" msgid="7113724443198337683">"<xliff:g id="APP_NAME">%1$s</xliff:g> შეძლებს თქვენს შეტყობინებებთან ინტერაქციას და თქვენი ტელეფონის, SMS-ების, კონტაქტებისა და კალენდრის ნებართვებზე წვდომას."</string>
- <string name="title_app_streaming" msgid="4459136600249308574">"გსურთ <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong>-ს მისცეთ აპების სტრიმინგის საშუალება?"</string>
+ <string name="permission_apps" msgid="6142133265286656158">"აპები"</string>
+ <string name="permission_apps_summary" msgid="798718816711515431">"თქვენი ტელეფონის აპების სტრიმინგი"</string>
+ <string name="title_app_streaming" msgid="2270331024626446950">"ნება დართეთ, რომ <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> აპს ჰქონდეს ამ ინფორმაციაზე წვდომა თქვენი ტელეფონიდან"</string>
<string name="summary_app_streaming" product="default" msgid="6105916810614498138">"მიეცით <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong>-ს საშუალება, <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong>-ისთვის დაუშვას დისტანციური წვდომა ამ ტელეფონზე დაინსტალირებულ აპებზე მასთან დაკავშირებისას."</string>
<string name="summary_app_streaming" product="tablet" msgid="2996373715966272792">"მიეცით <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong>-ს საშუალება, <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong>-ისთვის დაუშვას დისტანციური წვდომა ამ ტაბლეტზე დაინსტალირებულ აპებზე მასთან დაკავშირებისას."</string>
<string name="summary_app_streaming" product="device" msgid="7614171699434639963">"მიეცით <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong>-ს საშუალება, <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong>-ისთვის დაუშვას დისტანციური წვდომა ამ მოწყობილობაზე დაინსტალირებულ აპებზე მასთან დაკავშირებისას."</string>
+ <string name="helper_title_app_streaming" msgid="4151687003439969765">"მოწყობილობათშორისი სერვისები"</string>
+ <string name="helper_summary_app_streaming" msgid="5344341720432827388">"ეს სერვისი გამოიყენება აპების მოწყობილობებს შორის სტრიმინგისთვის"</string>
<string name="title_automotive_projection" msgid="3296005598978412847"></string>
<string name="summary_automotive_projection" msgid="8683801274662496164"></string>
<string name="title_computer" msgid="4693714143506569253">"ნება დართეთ, რომ <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> აპს ჰქონდეს ამ ინფორმაციაზე წვდომა თქვენი ტელეფონიდან"</string>
<string name="summary_computer" msgid="3798467601598297062"></string>
+ <string name="permission_notification" msgid="693762568127741203">"შეტყობინებები"</string>
+ <string name="permission_notification_summary" msgid="4398672775023193663">"შეუძლია წაიკითხოს ყველა შეტყობინება, მათ შორის ისეთი ინფორმაცია, როგორიცაა კონტრაქტები, ტექსტური გზავნილები და ფოტოები"</string>
+ <string name="permission_storage" msgid="6831099350839392343">"ფოტოები და მედია"</string>
+ <string name="permission_storage_summary" msgid="3918240895519506417"></string>
+ <string name="helper_title_computer" msgid="4671071173916176037">"Google Play services"</string>
+ <string name="helper_summary_computer" product="default" msgid="467996390095403648">"ეს სერვისი ფოტოებს, მედიას და შეტყობინებებს აზიარებს თქვენი ტელეფონიდან სხვა მოწყობილობებზე"</string>
+ <string name="helper_summary_computer" product="tablet" msgid="467996390095403648">"ეს სერვისი ფოტოებს, მედიას და შეტყობინებებს აზიარებს თქვენი ტელეფონიდან სხვა მოწყობილობებზე"</string>
<string name="profile_name_generic" msgid="6851028682723034988">"მოწყობილობა"</string>
<string name="summary_generic" msgid="2346762210105903720"></string>
<string name="consent_yes" msgid="8344487259618762872">"დაშვება"</string>
<string name="consent_no" msgid="2640796915611404382">"არ დაიშვას"</string>
+ <string name="consent_ok" msgid="3662376764371001106">"კარგი"</string>
<string name="permission_sync_confirmation_title" msgid="667074294393493186">"აპის ნებართვების საათისთვის გადაცემა"</string>
<string name="permission_sync_summary" msgid="8873391306499120778">"საათის დაყენების გასამარტივებლად თქვენს საათში დაინსტალირებული აპები იმავე ნებართვებს გამოიყენებს, რასაც ტელეფონზე იყენებს.\n\n ეს ნებართვები, შესაძლოა, მოიცავდეს თქვენი საათის მიკროფონსა და მდებარეობაზე წვდომას."</string>
</resources>
diff --git a/packages/CompanionDeviceManager/res/values-kk/strings.xml b/packages/CompanionDeviceManager/res/values-kk/strings.xml
index a7efb15..365020c5 100644
--- a/packages/CompanionDeviceManager/res/values-kk/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-kk/strings.xml
@@ -22,18 +22,30 @@
<string name="chooser_title" msgid="2262294130493605839">"<strong><xliff:g id="APP_NAME">%2$s</xliff:g></strong> арқылы басқарылатын <xliff:g id="PROFILE_NAME">%1$s</xliff:g> құрылғысын таңдаңыз"</string>
<string name="summary_watch" product="default" msgid="7113724443198337683">"<xliff:g id="APP_NAME">%1$s</xliff:g> қолданбасы хабарландыруларды, телефонды, SMS хабардарын, контактілерді және күнтізбе рұқсаттарын пайдалана алады."</string>
<string name="summary_watch" product="tablet" msgid="7113724443198337683">"<xliff:g id="APP_NAME">%1$s</xliff:g> қолданбасы хабарландыруларды, телефонды, SMS хабардарын, контактілерді және күнтізбе рұқсаттарын пайдалана алады."</string>
- <string name="title_app_streaming" msgid="4459136600249308574">"<strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> қолданбасына қолданбаларды трансляциялауға рұқсат етілсін бе?"</string>
+ <string name="permission_apps" msgid="6142133265286656158">"Қолданбалар"</string>
+ <string name="permission_apps_summary" msgid="798718816711515431">"Телефон қолданбаларын трансляциялайды."</string>
+ <string name="title_app_streaming" msgid="2270331024626446950">"<strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> қолданбасына телефоныңыздағы осы ақпаратты пайдалануға рұқсат беріңіз."</string>
<string name="summary_app_streaming" product="default" msgid="6105916810614498138">"<strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong> желіге қосылған кезде, <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> қолданбасына осы телефонға орнатылған қолданбаларды қашықтан пайдалануына рұқсат етіңіз."</string>
<string name="summary_app_streaming" product="tablet" msgid="2996373715966272792">"<strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong> желіге қосылған кезде, <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> қолданбасына осы планшетке орнатылған қолданбаларды қашықтан пайдалануына рұқсат етіңіз."</string>
<string name="summary_app_streaming" product="device" msgid="7614171699434639963">"<strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong> желіге қосылған кезде, <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> қолданбасына осы құрылғыға орнатылған қолданбаларды қашықтан пайдалануына рұқсат етіңіз."</string>
+ <string name="helper_title_app_streaming" msgid="4151687003439969765">"Аралық құрылғы қызметтері"</string>
+ <string name="helper_summary_app_streaming" msgid="5344341720432827388">"Бұл қызмет құрылғылар арасында қолданбаларды трансляциялау үшін пайдаланылады."</string>
<string name="title_automotive_projection" msgid="3296005598978412847"></string>
<string name="summary_automotive_projection" msgid="8683801274662496164"></string>
<string name="title_computer" msgid="4693714143506569253">"<strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> қолданбасына телефоныңыздағы осы ақпаратты пайдалануға рұқсат беріңіз."</string>
<string name="summary_computer" msgid="3798467601598297062"></string>
+ <string name="permission_notification" msgid="693762568127741203">"Хабарландырулар"</string>
+ <string name="permission_notification_summary" msgid="4398672775023193663">"Барлық хабарландыруды, соның ішінде контактілер, хабарлар және фотосуреттер сияқты ақпаратты оқи алады."</string>
+ <string name="permission_storage" msgid="6831099350839392343">"Фотосуреттер мен медиафайлдар"</string>
+ <string name="permission_storage_summary" msgid="3918240895519506417"></string>
+ <string name="helper_title_computer" msgid="4671071173916176037">"Google Play қызметтері"</string>
+ <string name="helper_summary_computer" product="default" msgid="467996390095403648">"Бұл қызмет телефоныңыздағы фотосуреттерді, мультимедианы және хабарландыруларды басқа құрылғылармен бөліседі."</string>
+ <string name="helper_summary_computer" product="tablet" msgid="467996390095403648">"Бұл қызмет телефоныңыздағы фотосуреттерді, мультимедианы және хабарландыруларды басқа құрылғылармен бөліседі."</string>
<string name="profile_name_generic" msgid="6851028682723034988">"құрылғы"</string>
<string name="summary_generic" msgid="2346762210105903720"></string>
<string name="consent_yes" msgid="8344487259618762872">"Рұқсат беру"</string>
<string name="consent_no" msgid="2640796915611404382">"Рұқсат бермеу"</string>
+ <string name="consent_ok" msgid="3662376764371001106">"Жарайды"</string>
<string name="permission_sync_confirmation_title" msgid="667074294393493186">"Қолданба рұқсаттарын сағатқа ауыстыру"</string>
<string name="permission_sync_summary" msgid="8873391306499120778">"Реттеу кезінде сағатқа орнатылған қолданбалар телефондағыдай рұқсаттарды пайдаланады. Осылайша сағат оңай реттеледі.\n\n Бұл рұқсаттар сағаттың микрофоны мен геодерегін пайдалануды қамтиды."</string>
</resources>
diff --git a/packages/CompanionDeviceManager/res/values-km/strings.xml b/packages/CompanionDeviceManager/res/values-km/strings.xml
index b185863..e1dbaf5 100644
--- a/packages/CompanionDeviceManager/res/values-km/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-km/strings.xml
@@ -22,18 +22,30 @@
<string name="chooser_title" msgid="2262294130493605839">"ជ្រើសរើស <xliff:g id="PROFILE_NAME">%1$s</xliff:g> ដើម្បីឱ្យស្ថិតក្រោមការគ្រប់គ្រងរបស់ <strong><xliff:g id="APP_NAME">%2$s</xliff:g></strong>"</string>
<string name="summary_watch" product="default" msgid="7113724443198337683">"<xliff:g id="APP_NAME">%1$s</xliff:g> នឹងត្រូវបានអនុញ្ញាតឱ្យធ្វើអន្តរកម្មជាមួយការជូនដំណឹងរបស់អ្នក និងចូលប្រើការអនុញ្ញាតប្រតិទិន, ទូរសព្ទ, SMS និងទំនាក់ទំនងរបស់អ្នក។"</string>
<string name="summary_watch" product="tablet" msgid="7113724443198337683">"<xliff:g id="APP_NAME">%1$s</xliff:g> នឹងត្រូវបានអនុញ្ញាតឱ្យធ្វើអន្តរកម្មជាមួយការជូនដំណឹងរបស់អ្នក និងចូលប្រើការអនុញ្ញាតប្រតិទិន, ទូរសព្ទ, SMS និងទំនាក់ទំនងរបស់អ្នក។"</string>
- <string name="title_app_streaming" msgid="4459136600249308574">"អនុញ្ញាតឱ្យ <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> ផ្សាយកម្មវិធីឬ?"</string>
+ <string name="permission_apps" msgid="6142133265286656158">"កម្មវិធី"</string>
+ <string name="permission_apps_summary" msgid="798718816711515431">"បញ្ចាំងកម្មវិធីរបស់ទូរសព្ទអ្នក"</string>
+ <string name="title_app_streaming" msgid="2270331024626446950">"អនុញ្ញាតឱ្យ <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> ចូលប្រើព័ត៌មាននេះពីទូរសព្ទរបស់អ្នក"</string>
<string name="summary_app_streaming" product="default" msgid="6105916810614498138">"អនុញ្ញាតឱ្យ <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> ផ្ដល់ការចូលប្រើពីចម្ងាយដល់ <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong> ដើម្បីចូលប្រើកម្មវិធី ដែលបានដំឡើងនៅលើទូរសព្ទនេះ នៅពេលភ្ជាប់អ៊ីនធឺណិត។"</string>
<string name="summary_app_streaming" product="tablet" msgid="2996373715966272792">"អនុញ្ញាតឱ្យ <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> ផ្ដល់ការចូលប្រើពីចម្ងាយដល់ <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong> ដើម្បីចូលប្រើកម្មវិធី ដែលបានដំឡើងនៅលើថេប្លេតនេះ នៅពេលភ្ជាប់អ៊ីនធឺណិត។"</string>
<string name="summary_app_streaming" product="device" msgid="7614171699434639963">"អនុញ្ញាតឱ្យ <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> ផ្ដល់ការចូលប្រើពីចម្ងាយដល់ <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong> ដើម្បីចូលប្រើកម្មវិធី ដែលបានដំឡើងនៅលើឧបករណ៍នេះ នៅពេលភ្ជាប់អ៊ីនធឺណិត។"</string>
+ <string name="helper_title_app_streaming" msgid="4151687003439969765">"សេវាកម្មឆ្លងកាត់ឧបករណ៍"</string>
+ <string name="helper_summary_app_streaming" msgid="5344341720432827388">"សេវាកម្មនេះត្រូវបានប្រើដើម្បីភ្ជាប់កម្មវិធីរវាងឧបករណ៍របស់អ្នក"</string>
<string name="title_automotive_projection" msgid="3296005598978412847"></string>
<string name="summary_automotive_projection" msgid="8683801274662496164"></string>
<string name="title_computer" msgid="4693714143506569253">"អនុញ្ញាតឱ្យ <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> ចូលមើលព័ត៌មាននេះពីទូរសព្ទរបស់អ្នក"</string>
<string name="summary_computer" msgid="3798467601598297062"></string>
+ <string name="permission_notification" msgid="693762568127741203">"ការជូនដំណឹង"</string>
+ <string name="permission_notification_summary" msgid="4398672775023193663">"អាចអានការជូនដំណឹងទាំងអស់ រួមទាំងព័ត៌មានដូចជាទំនាក់ទំនង សារ និងរូបថត"</string>
+ <string name="permission_storage" msgid="6831099350839392343">"រូបថត និងមេឌៀ"</string>
+ <string name="permission_storage_summary" msgid="3918240895519506417"></string>
+ <string name="helper_title_computer" msgid="4671071173916176037">"សេវាកម្ម Google Play"</string>
+ <string name="helper_summary_computer" product="default" msgid="467996390095403648">"សេវាកម្មនេះចែករំលែករូបថត មេឌៀ និងការជូនដំណឹងពីទូរសព្ទរបស់អ្នកទៅឧបករណ៍ផ្សេងទៀត"</string>
+ <string name="helper_summary_computer" product="tablet" msgid="467996390095403648">"សេវាកម្មនេះចែករំលែករូបថត មេឌៀ និងការជូនដំណឹងពីទូរសព្ទរបស់អ្នកទៅឧបករណ៍ផ្សេងទៀត"</string>
<string name="profile_name_generic" msgid="6851028682723034988">"ឧបករណ៍"</string>
<string name="summary_generic" msgid="2346762210105903720"></string>
<string name="consent_yes" msgid="8344487259618762872">"អនុញ្ញាត"</string>
<string name="consent_no" msgid="2640796915611404382">"កុំអនុញ្ញាត"</string>
+ <string name="consent_ok" msgid="3662376764371001106">"យល់ព្រម"</string>
<string name="permission_sync_confirmation_title" msgid="667074294393493186">"ផ្ទេរការអនុញ្ញាតកម្មវិធីទៅនាឡិការបស់អ្នក"</string>
<string name="permission_sync_summary" msgid="8873391306499120778">"ដើម្បីជួយឱ្យការរៀបចំនាឡិការបស់អ្នកកាន់តែងាយស្រួល កម្មវិធីដែលបានដំឡើងនៅលើនាឡិការបស់អ្នកអំឡុងពេលរៀបចំនឹងប្រើការអនុញ្ញាតដូចគ្នានឹងទូរសព្ទរបស់អ្នកដែរ។\n\n ការអនុញ្ញាតទាំងនេះអាចរួមបញ្ចូលសិទ្ធិចូលប្រើទីតាំង និងមីក្រូហ្វូនរបស់នាឡិកាអ្នក។"</string>
</resources>
diff --git a/packages/CompanionDeviceManager/res/values-kn/strings.xml b/packages/CompanionDeviceManager/res/values-kn/strings.xml
index 64576ce..0d01ce7 100644
--- a/packages/CompanionDeviceManager/res/values-kn/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-kn/strings.xml
@@ -22,18 +22,30 @@
<string name="chooser_title" msgid="2262294130493605839">"<strong><xliff:g id="APP_NAME">%2$s</xliff:g></strong> ಮೂಲಕ ನಿರ್ವಹಿಸಬೇಕಾದ <xliff:g id="PROFILE_NAME">%1$s</xliff:g> ಅನ್ನು ಆಯ್ಕೆಮಾಡಿ"</string>
<string name="summary_watch" product="default" msgid="7113724443198337683">"ನಿಮ್ಮ ಅಧಿಸೂಚನೆಗಳೊಂದಿಗೆ ಸಂವಹನ ನಡೆಸಲು ಮತ್ತು ನಿಮ್ಮ ಫೋನ್, SMS, ಸಂಪರ್ಕಗಳು ಮತ್ತು Calendar ಅನುಮತಿಗಳನ್ನು ಪ್ರವೇಶಿಸಲು <xliff:g id="APP_NAME">%1$s</xliff:g> ಗೆ ಅನುಮತಿಸಲಾಗುತ್ತದೆ."</string>
<string name="summary_watch" product="tablet" msgid="7113724443198337683">"ನಿಮ್ಮ ಅಧಿಸೂಚನೆಗಳೊಂದಿಗೆ ಸಂವಹನ ನಡೆಸಲು ಮತ್ತು ನಿಮ್ಮ ಫೋನ್, SMS, ಸಂಪರ್ಕಗಳು ಮತ್ತು Calendar ಅನುಮತಿಗಳನ್ನು ಪ್ರವೇಶಿಸಲು <xliff:g id="APP_NAME">%1$s</xliff:g> ಗೆ ಅನುಮತಿಸಲಾಗುತ್ತದೆ."</string>
- <string name="title_app_streaming" msgid="4459136600249308574">"ಆ್ಯಪ್ಗಳನ್ನು ಸ್ಟ್ರೀಮ್ ಮಾಡಲು <xliff:g id="APP_NAME">%1$s</xliff:g> ಗೆ ಅನುಮತಿಸಿ?"</string>
+ <string name="permission_apps" msgid="6142133265286656158">"ಆ್ಯಪ್ಗಳು"</string>
+ <string name="permission_apps_summary" msgid="798718816711515431">"ನಿಮ್ಮ ಫೋನ್ನ ಆ್ಯಪ್ಗಳನ್ನು ಸ್ಟ್ರೀಮ್ ಮಾಡಿ"</string>
+ <string name="title_app_streaming" msgid="2270331024626446950">"ನಿಮ್ಮ ಫೋನ್ ಮೂಲಕ ಈ ಮಾಹಿತಿಯನ್ನು ಆ್ಯಕ್ಸೆಸ್ ಮಾಡಲು <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> ಗೆ ಅನುಮತಿಸಿ"</string>
<string name="summary_app_streaming" product="default" msgid="6105916810614498138">"ಕನೆಕ್ಟ್ ಆದಾಗ ಈ ಫೋನ್ನಲ್ಲಿ ಇನ್ಸ್ಟಾಲ್ ಮಾಡಲಾದ ಆ್ಯಪ್ಗಳನ್ನು ಪ್ರವೇಶಿಸುವುದಕ್ಕಾಗಿ <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong> ಗೆ ರಿಮೋಟ್ ಪ್ರವೇಶವನ್ನು ಒದಗಿಸಲು <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> ಗೆ ಅನುಮತಿಸಿ."</string>
<string name="summary_app_streaming" product="tablet" msgid="2996373715966272792">"ಕನೆಕ್ಟ್ ಆದಾಗ ಈ ಟ್ಯಾಬ್ಲೆಟ್ನಲ್ಲಿ ಇನ್ಸ್ಟಾಲ್ ಮಾಡಲಾದ ಆ್ಯಪ್ಗಳನ್ನು ಪ್ರವೇಶಿಸುವುದಕ್ಕಾಗಿ <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong> ಗೆ ರಿಮೋಟ್ ಪ್ರವೇಶವನ್ನು ಒದಗಿಸಲು <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> ಗೆ ಅನುಮತಿಸಿ."</string>
<string name="summary_app_streaming" product="device" msgid="7614171699434639963">"ಕನೆಕ್ಟ್ ಆದಾಗ ಈ ಸಾಧನದಲ್ಲಿ ಇನ್ಸ್ಟಾಲ್ ಮಾಡಲಾದ ಆ್ಯಪ್ಗಳನ್ನು ಪ್ರವೇಶಿಸುವುದಕ್ಕಾಗಿ <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong> ಗೆ ರಿಮೋಟ್ ಪ್ರವೇಶವನ್ನು ಒದಗಿಸಲು <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> ಗೆ ಅನುಮತಿಸಿ."</string>
+ <string name="helper_title_app_streaming" msgid="4151687003439969765">"ಕ್ರಾಸ್-ಸಾಧನ ಸೇವೆಗಳು"</string>
+ <string name="helper_summary_app_streaming" msgid="5344341720432827388">"ನಿಮ್ಮ ಸಾಧನಗಳ ನಡುವೆ ಆ್ಯಪ್ಗಳನ್ನು ಸ್ಟ್ರೀಮ್ ಮಾಡಲು ಈ ಸೇವೆಯನ್ನು ಬಳಸಲಾಗುತ್ತದೆ"</string>
<string name="title_automotive_projection" msgid="3296005598978412847"></string>
<string name="summary_automotive_projection" msgid="8683801274662496164"></string>
<string name="title_computer" msgid="4693714143506569253">"ನಿಮ್ಮ ಫೋನ್ ಮೂಲಕ ಈ ಮಾಹಿತಿಯನ್ನು ಪ್ರವೇಶಿಸಲು <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> ಗೆ ಅನುಮತಿಸಿ"</string>
<string name="summary_computer" msgid="3798467601598297062"></string>
+ <string name="permission_notification" msgid="693762568127741203">"ಅಧಿಸೂಚನೆಗಳು"</string>
+ <string name="permission_notification_summary" msgid="4398672775023193663">"ಒಪ್ಪಂದಗಳು, ಸಂದೇಶಗಳು ಮತ್ತು ಫೋಟೋಗಳಂತಹ ಮಾಹಿತಿಯನ್ನು ಒಳಗೊಂಡಂತೆ ಎಲ್ಲಾ ಅಧಿಸೂಚನೆಗಳನ್ನು ಓದಬಹುದು"</string>
+ <string name="permission_storage" msgid="6831099350839392343">"ಫೋಟೋಗಳು ಮತ್ತು ಮಾಧ್ಯಮ"</string>
+ <string name="permission_storage_summary" msgid="3918240895519506417"></string>
+ <string name="helper_title_computer" msgid="4671071173916176037">"Google Play ಸೇವೆಗಳು"</string>
+ <string name="helper_summary_computer" product="default" msgid="467996390095403648">"ಈ ಸೇವೆಯು, ನಿಮ್ಮ ಫೋನ್ನಿಂದ ಇತರ ಸಾಧನಗಳಿಗೆ ಫೋಟೋಗಳು, ಮಾಧ್ಯಮ ಮತ್ತು ಅಧಿಸೂಚನೆಗಳನ್ನು ಹಂಚಿಕೊಳ್ಳುತ್ತದೆ"</string>
+ <string name="helper_summary_computer" product="tablet" msgid="467996390095403648">"ಈ ಸೇವೆಯು, ನಿಮ್ಮ ಫೋನ್ನಿಂದ ಇತರ ಸಾಧನಗಳಿಗೆ ಫೋಟೋಗಳು, ಮಾಧ್ಯಮ ಮತ್ತು ಅಧಿಸೂಚನೆಗಳನ್ನು ಹಂಚಿಕೊಳ್ಳುತ್ತದೆ"</string>
<string name="profile_name_generic" msgid="6851028682723034988">"ಸಾಧನ"</string>
<string name="summary_generic" msgid="2346762210105903720"></string>
<string name="consent_yes" msgid="8344487259618762872">"ಅನುಮತಿಸಿ"</string>
<string name="consent_no" msgid="2640796915611404382">"ಅನುಮತಿಸಬೇಡಿ"</string>
+ <string name="consent_ok" msgid="3662376764371001106">"ಸರಿ"</string>
<string name="permission_sync_confirmation_title" msgid="667074294393493186">"ಆ್ಯಪ್ ಅನುಮತಿಗಳನ್ನು ನಿಮ್ಮ ವಾಚ್ಗೆ ವರ್ಗಾವಣೆ ಮಾಡಿ"</string>
<string name="permission_sync_summary" msgid="8873391306499120778">"ನಿಮ್ಮ ವಾಚ್ ಸೆಟಪ್ ಮಾಡುವುದನ್ನು ಸುಲಭವಾಗಿಸಲು, ಸೆಟಪ್ನ ಸಮಯದಲ್ಲಿ ನಿಮ್ಮ ವಾಚ್ನಲ್ಲಿ ಇನ್ಸ್ಟಾಲ್ ಮಾಡಿದ ಆ್ಯಪ್ಗಳು, ನಿಮ್ಮ ಫೋನ್ನಲ್ಲಿನ ಅನುಮತಿಗಳನ್ನೇ ಬಳಸಿಕೊಳ್ಳುತ್ತವೆ.\n\n ಈ ಅನುಮತಿಗಳು ನಿಮ್ಮ ವಾಚ್ನ ಮೈಕ್ರೊಫೋನ್ ಮತ್ತು ಸ್ಥಳದ ಪ್ರವೇಶವನ್ನು ಒಳಗೊಳ್ಳಬಹುದು."</string>
</resources>
diff --git a/packages/CompanionDeviceManager/res/values-ko/strings.xml b/packages/CompanionDeviceManager/res/values-ko/strings.xml
index 5bf8eb4..2b98ce3 100644
--- a/packages/CompanionDeviceManager/res/values-ko/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-ko/strings.xml
@@ -22,18 +22,30 @@
<string name="chooser_title" msgid="2262294130493605839">"<strong><xliff:g id="APP_NAME">%2$s</xliff:g></strong>에서 관리할 <xliff:g id="PROFILE_NAME">%1$s</xliff:g>을(를) 선택"</string>
<string name="summary_watch" product="default" msgid="7113724443198337683">"<xliff:g id="APP_NAME">%1$s</xliff:g>에서 알림과 상호작용하고 전화, SMS, 연락처, 캘린더 권한에 액세스할 수 있게 됩니다."</string>
<string name="summary_watch" product="tablet" msgid="7113724443198337683">"<xliff:g id="APP_NAME">%1$s</xliff:g>에서 알림과 상호작용하고 전화, SMS, 연락처, 캘린더 권한에 액세스할 수 있게 됩니다."</string>
- <string name="title_app_streaming" msgid="4459136600249308574">"<strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong>에서 애플리케이션을 스트리밍하도록 허용하시겠습니까?"</string>
+ <string name="permission_apps" msgid="6142133265286656158">"앱"</string>
+ <string name="permission_apps_summary" msgid="798718816711515431">"휴대전화의 앱을 스트리밍합니다."</string>
+ <string name="title_app_streaming" msgid="2270331024626446950">"<strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> 앱이 휴대전화에서 이 정보에 액세스하도록 허용합니다."</string>
<string name="summary_app_streaming" product="default" msgid="6105916810614498138">"연결 시 <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong>에서 <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong>에 이 휴대전화에 설치된 애플리케이션에 원격으로 액세스할 수 있는 권한을 제공하도록 허용합니다."</string>
<string name="summary_app_streaming" product="tablet" msgid="2996373715966272792">"연결 시 <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong>에서 <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong>에 이 태블릿에 설치된 애플리케이션에 원격으로 액세스할 수 있는 권한을 제공하도록 허용합니다."</string>
<string name="summary_app_streaming" product="device" msgid="7614171699434639963">"연결 시 <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong>에서 <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong>에 이 기기에 설치된 애플리케이션에 원격으로 액세스할 수 있는 권한을 제공하도록 허용합니다."</string>
+ <string name="helper_title_app_streaming" msgid="4151687003439969765">"교차 기기 서비스"</string>
+ <string name="helper_summary_app_streaming" msgid="5344341720432827388">"이 서비스는 기기 간에 앱을 스트리밍하는 데 사용됩니다."</string>
<string name="title_automotive_projection" msgid="3296005598978412847"></string>
<string name="summary_automotive_projection" msgid="8683801274662496164"></string>
<string name="title_computer" msgid="4693714143506569253">"<strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> 앱이 휴대전화에서 이 정보에 액세스하도록 허용합니다."</string>
<string name="summary_computer" msgid="3798467601598297062"></string>
+ <string name="permission_notification" msgid="693762568127741203">"알림"</string>
+ <string name="permission_notification_summary" msgid="4398672775023193663">"연락처, 메시지, 사진 등의 정보를 포함한 모든 알림을 읽을 수 있습니다."</string>
+ <string name="permission_storage" msgid="6831099350839392343">"사진 및 미디어"</string>
+ <string name="permission_storage_summary" msgid="3918240895519506417"></string>
+ <string name="helper_title_computer" msgid="4671071173916176037">"Google Play 서비스"</string>
+ <string name="helper_summary_computer" product="default" msgid="467996390095403648">"이 서비스는 휴대전화의 사진, 미디어 및 알림을 다른 기기와 공유합니다."</string>
+ <string name="helper_summary_computer" product="tablet" msgid="467996390095403648">"이 서비스는 휴대전화의 사진, 미디어 및 알림을 다른 기기와 공유합니다."</string>
<string name="profile_name_generic" msgid="6851028682723034988">"기기"</string>
<string name="summary_generic" msgid="2346762210105903720"></string>
<string name="consent_yes" msgid="8344487259618762872">"허용"</string>
<string name="consent_no" msgid="2640796915611404382">"허용 안함"</string>
+ <string name="consent_ok" msgid="3662376764371001106">"확인"</string>
<string name="permission_sync_confirmation_title" msgid="667074294393493186">"앱 권한을 시계로 이전"</string>
<string name="permission_sync_summary" msgid="8873391306499120778">"시계를 더 쉽게 설정하기 위해 설정하는 동안 시계에 설치된 앱에서 휴대전화와 동일한 권한을 사용합니다.\n\n 이러한 권한에는 시계의 마이크 및 위치 정보에 대한 액세스가 포함될 수 있습니다."</string>
</resources>
diff --git a/packages/CompanionDeviceManager/res/values-ky/strings.xml b/packages/CompanionDeviceManager/res/values-ky/strings.xml
index 714dc93..1f320dd 100644
--- a/packages/CompanionDeviceManager/res/values-ky/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-ky/strings.xml
@@ -22,18 +22,30 @@
<string name="chooser_title" msgid="2262294130493605839">"<xliff:g id="PROFILE_NAME">%1$s</xliff:g> <strong><xliff:g id="APP_NAME">%2$s</xliff:g></strong> тарабынан башкарылсын"</string>
<string name="summary_watch" product="default" msgid="7113724443198337683">"<xliff:g id="APP_NAME">%1$s</xliff:g> билдирмелериңизди көрүп, телефонуңуздун, SMS билдирүүлөрүңүздүн, байланыштарыңыздын жана жылнаамаңыздын уруксаттарын пайдалана алат."</string>
<string name="summary_watch" product="tablet" msgid="7113724443198337683">"<xliff:g id="APP_NAME">%1$s</xliff:g> билдирмелериңизди көрүп, телефонуңуздун, SMS билдирүүлөрүңүздүн, байланыштарыңыздын жана жылнаамаңыздын уруксаттарын пайдалана алат."</string>
- <string name="title_app_streaming" msgid="4459136600249308574">"<strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> колдонмосуна колдонмолорду алып ойнотууга уруксат бересизби?"</string>
+ <string name="permission_apps" msgid="6142133265286656158">"Колдонмолор"</string>
+ <string name="permission_apps_summary" msgid="798718816711515431">"Телефондогу колдонмолорду алып ойнотуу"</string>
+ <string name="title_app_streaming" msgid="2270331024626446950">"<strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> колдонмосуна телефонуңуздагы ушул маалыматты көрүүгө уруксат бериңиз"</string>
<string name="summary_app_streaming" product="default" msgid="6105916810614498138">"<strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> колдонмосуна Интернетке туташкан <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong> телефонундагы колдонмолорго алыстан кирүү мүмкүнчүлүгүн бериңиз."</string>
<string name="summary_app_streaming" product="tablet" msgid="2996373715966272792">"<strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> колдонмосуна Интернетке туташкан <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong> планшетиндеги колдонмолорго алыстан кирүү мүмкүнчүлүгүн бериңиз."</string>
<string name="summary_app_streaming" product="device" msgid="7614171699434639963">"<strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> колдонмосуна Интернетке туташкан <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong> түзмөгүндөгү колдонмолорго алыстан кирүү мүмкүнчүлүгүн бериңиз."</string>
+ <string name="helper_title_app_streaming" msgid="4151687003439969765">"Түзмөктөр аралык кызматтар"</string>
+ <string name="helper_summary_app_streaming" msgid="5344341720432827388">"Бул кызмат түзмөктөрүңүздүн ортосунда колдонмолорду тышкы экранга чыгаруу үчүн колдонулат"</string>
<string name="title_automotive_projection" msgid="3296005598978412847"></string>
<string name="summary_automotive_projection" msgid="8683801274662496164"></string>
<string name="title_computer" msgid="4693714143506569253">"<strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> колдонмосуна телефонуңуздагы ушул маалыматты көрүүгө уруксат бериңиз"</string>
<string name="summary_computer" msgid="3798467601598297062"></string>
+ <string name="permission_notification" msgid="693762568127741203">"Билдирмелер"</string>
+ <string name="permission_notification_summary" msgid="4398672775023193663">"Бардык билдирмелерди, анын ичинде байланыштар, билдирүүлөр жана сүрөттөр сыяктуу маалыматты окуй алат"</string>
+ <string name="permission_storage" msgid="6831099350839392343">"Сүрөттөр жана медиа"</string>
+ <string name="permission_storage_summary" msgid="3918240895519506417"></string>
+ <string name="helper_title_computer" msgid="4671071173916176037">"Google Play кызматтары"</string>
+ <string name="helper_summary_computer" product="default" msgid="467996390095403648">"Бул кызмат сүрөттөрдү, медиа файлдарды жана билдирмелерди телефонуңуздан башка түзмөктөр менен бөлүшөт"</string>
+ <string name="helper_summary_computer" product="tablet" msgid="467996390095403648">"Бул кызмат сүрөттөрдү, медиа файлдарды жана билдирмелерди телефонуңуздан башка түзмөктөр менен бөлүшөт"</string>
<string name="profile_name_generic" msgid="6851028682723034988">"түзмөк"</string>
<string name="summary_generic" msgid="2346762210105903720"></string>
<string name="consent_yes" msgid="8344487259618762872">"Уруксат берүү"</string>
<string name="consent_no" msgid="2640796915611404382">"Уруксат берилбесин"</string>
+ <string name="consent_ok" msgid="3662376764371001106">"Макул"</string>
<string name="permission_sync_confirmation_title" msgid="667074294393493186">"Колдонмонун уруксаттарын саатка өткөрүү"</string>
<string name="permission_sync_summary" msgid="8873391306499120778">"Сааттын жөндөлүшүн жеңилдетүү үчүн жөндөө учурунда саатыңызга орнотулган колдонмолор телефонуңуздагы уруксаттарды колдонот.\n\n Мындай уруксаттарга саатыңыздын микрофонун же жайгашкан жерин колдонуу кириши мүмкүн."</string>
</resources>
diff --git a/packages/CompanionDeviceManager/res/values-lo/strings.xml b/packages/CompanionDeviceManager/res/values-lo/strings.xml
index 95cab69..debbf76 100644
--- a/packages/CompanionDeviceManager/res/values-lo/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-lo/strings.xml
@@ -22,18 +22,30 @@
<string name="chooser_title" msgid="2262294130493605839">"ເລືອກ <xliff:g id="PROFILE_NAME">%1$s</xliff:g> ເພື່ອໃຫ້ຖືກຈັດການໂດຍ <strong><xliff:g id="APP_NAME">%2$s</xliff:g></strong>"</string>
<string name="summary_watch" product="default" msgid="7113724443198337683">"<xliff:g id="APP_NAME">%1$s</xliff:g> ຈະໄດ້ຮັບອະນຸຍາດໃຫ້ໂຕ້ຕອບກັບການແຈ້ງເຕືອນຂອງທ່ານ ແລະ ເຂົ້າເຖິງການອະນຸຍາດໂທລະສັບ, SMS, ລາຍຊື່ຜູ້ຕິດຕໍ່ ແລະ ປະຕິທິນຂອງທ່ານໄດ້."</string>
<string name="summary_watch" product="tablet" msgid="7113724443198337683">"<xliff:g id="APP_NAME">%1$s</xliff:g> ຈະໄດ້ຮັບອະນຸຍາດໃຫ້ໂຕ້ຕອບກັບການແຈ້ງເຕືອນຂອງທ່ານ ແລະ ເຂົ້າເຖິງການອະນຸຍາດໂທລະສັບ, SMS, ລາຍຊື່ຜູ້ຕິດຕໍ່ ແລະ ປະຕິທິນຂອງທ່ານໄດ້."</string>
- <string name="title_app_streaming" msgid="4459136600249308574">"ອະນຸຍາດໃຫ້ <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> ສະຕຣີມແອັບພລິເຄຊັນໄດ້ບໍ?"</string>
+ <string name="permission_apps" msgid="6142133265286656158">"ແອັບ"</string>
+ <string name="permission_apps_summary" msgid="798718816711515431">"ສະຕຣີມແອັບຂອງໂທລະສັບທ່ານ"</string>
+ <string name="title_app_streaming" msgid="2270331024626446950">"ອະນຸຍາດ <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> ໃຫ້ເຂົ້າເຖິງຂໍ້ມູນນີ້ຈາກໂທລະສັບຂອງທ່ານໄດ້"</string>
<string name="summary_app_streaming" product="default" msgid="6105916810614498138">"ໃຫ້ສິດ <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> ເພື່ອເຂົ້າເຖິງ <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong> ຈາກໄລຍະໄກເພື່ອເຂົ້າເຖິງແອັບພລິເຄຊັນທີ່ຕິດຕັ້ງຢູ່ໂທລະສັບນີ້ເມື່ອເຊື່ອມຕໍ່ແລ້ວ."</string>
<string name="summary_app_streaming" product="tablet" msgid="2996373715966272792">"ໃຫ້ສິດ <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> ເພື່ອເຂົ້າເຖິງ <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong> ຈາກໄລຍະໄກເພື່ອເຂົ້າເຖິງແອັບພລິເຄຊັນທີ່ຕິດຕັ້ງຢູ່ແທັບເລັດນີ້ເມື່ອເຊື່ອມຕໍ່ແລ້ວ."</string>
<string name="summary_app_streaming" product="device" msgid="7614171699434639963">"ໃຫ້ສິດ <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> ເພື່ອເຂົ້າເຖິງ <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong> ຈາກໄລຍະໄກເພື່ອເຂົ້າເຖິງແອັບພລິເຄຊັນທີ່ຕິດຕັ້ງຢູ່ອຸປະກອນນີ້ເມື່ອເຊື່ອມຕໍ່ແລ້ວ."</string>
+ <string name="helper_title_app_streaming" msgid="4151687003439969765">"ບໍລິການຂ້າມອຸປະກອນ"</string>
+ <string name="helper_summary_app_streaming" msgid="5344341720432827388">"ບໍລິການນີ້ໃຊ້ເພື່ອສະຕຣີມແອັບລະຫວ່າງອຸປະກອນຂອງທ່ານ"</string>
<string name="title_automotive_projection" msgid="3296005598978412847"></string>
<string name="summary_automotive_projection" msgid="8683801274662496164"></string>
<string name="title_computer" msgid="4693714143506569253">"ອະນຸຍາດ <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> ໃຫ້ເຂົ້າເຖິງຂໍ້ມູນນີ້ຈາກໂທລະສັບຂອງທ່ານໄດ້"</string>
<string name="summary_computer" msgid="3798467601598297062"></string>
+ <string name="permission_notification" msgid="693762568127741203">"ການແຈ້ງເຕືອນ"</string>
+ <string name="permission_notification_summary" msgid="4398672775023193663">"ສາມາດອ່ານການແຈ້ງເຕືອນທັງໝົດ, ຮວມທັງຂໍ້ມູນ ເຊັ່ນ: ລາຍຊື່ຜູ້ຕິດຕໍ່, ຂໍ້ຄວາມ ແລະ ຮູບພາບ"</string>
+ <string name="permission_storage" msgid="6831099350839392343">"ຮູບພາບ ແລະ ມີເດຍ"</string>
+ <string name="permission_storage_summary" msgid="3918240895519506417"></string>
+ <string name="helper_title_computer" msgid="4671071173916176037">"ບໍລິການ Google Play"</string>
+ <string name="helper_summary_computer" product="default" msgid="467996390095403648">"ບໍລິການນີ້ຈະແບ່ງປັນຮູບພາບ, ມີເດຍ ແລະ ການແຈ້ງເຕືອນຈາກໂທລະສັບຂອງທ່ານໄປຫາອຸປະກອນອື່ນ"</string>
+ <string name="helper_summary_computer" product="tablet" msgid="467996390095403648">"ບໍລິການນີ້ຈະແບ່ງປັນຮູບພາບ, ມີເດຍ ແລະ ການແຈ້ງເຕືອນຈາກໂທລະສັບຂອງທ່ານໄປຫາອຸປະກອນອື່ນ"</string>
<string name="profile_name_generic" msgid="6851028682723034988">"ອຸປະກອນ"</string>
<string name="summary_generic" msgid="2346762210105903720"></string>
<string name="consent_yes" msgid="8344487259618762872">"ອະນຸຍາດ"</string>
<string name="consent_no" msgid="2640796915611404382">"ບໍ່ອະນຸຍາດ"</string>
+ <string name="consent_ok" msgid="3662376764371001106">"ຕົກລົງ"</string>
<string name="permission_sync_confirmation_title" msgid="667074294393493186">"ໂອນຍ້າຍການອະນຸຍາດແອັບໄປຫາໂມງຂອງທ່ານ"</string>
<string name="permission_sync_summary" msgid="8873391306499120778">"ເພື່ອເຮັດໃຫ້ຕັ້ງຄ່າໂມງຂອງທ່ານໄດ້ງ່າຍຂຶ້ນ, ແອັບທີ່ຕິດຕັ້ງຢູ່ໂມງຂອງທ່ານໃນລະຫວ່າງການຕັ້ງຄ່າຈະໃຊ້ການອະນຸຍາດດຽວກັນກັບໂທລະສັບຂອງທ່ານ.\n\n ການອະນຸຍາດເຫຼົ່ານີ້ອາດຮວມສິດເຂົ້າເຖິງໄມໂຄຣໂຟນ ແລະ ສະຖານທີ່ຂອງທ່ານນຳ."</string>
</resources>
diff --git a/packages/CompanionDeviceManager/res/values-lt/strings.xml b/packages/CompanionDeviceManager/res/values-lt/strings.xml
index 5d32fbb..3904ad3 100644
--- a/packages/CompanionDeviceManager/res/values-lt/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-lt/strings.xml
@@ -22,18 +22,30 @@
<string name="chooser_title" msgid="2262294130493605839">"Jūsų <xliff:g id="PROFILE_NAME">%1$s</xliff:g>, kurį valdys <strong><xliff:g id="APP_NAME">%2$s</xliff:g></strong> (pasirinkite)"</string>
<string name="summary_watch" product="default" msgid="7113724443198337683">"„<xliff:g id="APP_NAME">%1$s</xliff:g>“ galės sąveikauti su pranešimų funkcija ir pasiekti telefoną, SMS, kontaktus ir kalendorių."</string>
<string name="summary_watch" product="tablet" msgid="7113724443198337683">"„<xliff:g id="APP_NAME">%1$s</xliff:g>“ galės sąveikauti su pranešimų funkcija ir pasiekti telefoną, SMS, kontaktus ir kalendorių."</string>
- <string name="title_app_streaming" msgid="4459136600249308574">"Leisti <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> perduoti srautu programas?"</string>
+ <string name="permission_apps" msgid="6142133265286656158">"Programos"</string>
+ <string name="permission_apps_summary" msgid="798718816711515431">"Telefono programų perdavimas srautu"</string>
+ <string name="title_app_streaming" msgid="2270331024626446950">"Leisti <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> pasiekti šią informaciją iš jūsų telefono"</string>
<string name="summary_app_streaming" product="default" msgid="6105916810614498138">"Leiskite <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> prisijungus suteikti <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong> nuotolinę prieigą prie šiame telefone įdiegtų programų."</string>
<string name="summary_app_streaming" product="tablet" msgid="2996373715966272792">"Leiskite <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> prisijungus suteikti <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong> nuotolinę prieigą prie šiame planšetiniame kompiuteryje įdiegtų programų."</string>
<string name="summary_app_streaming" product="device" msgid="7614171699434639963">"Leiskite <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> prisijungus suteikti <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong> nuotolinę prieigą prie šiame įrenginyje įdiegtų programų."</string>
+ <string name="helper_title_app_streaming" msgid="4151687003439969765">"Pasl. keliuose įrenginiuose"</string>
+ <string name="helper_summary_app_streaming" msgid="5344341720432827388">"Ši paslauga naudojama perduoti programas srautu tarp jūsų įrenginių"</string>
<string name="title_automotive_projection" msgid="3296005598978412847"></string>
<string name="summary_automotive_projection" msgid="8683801274662496164"></string>
<string name="title_computer" msgid="4693714143506569253">"Leisti <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> pasiekti šią informaciją iš jūsų telefono"</string>
<string name="summary_computer" msgid="3798467601598297062"></string>
+ <string name="permission_notification" msgid="693762568127741203">"Pranešimai"</string>
+ <string name="permission_notification_summary" msgid="4398672775023193663">"Galima skaityti visus pranešimus, įskaitant tokią informaciją kaip sutartys, pranešimai ir nuotraukos"</string>
+ <string name="permission_storage" msgid="6831099350839392343">"Nuotraukos ir medija"</string>
+ <string name="permission_storage_summary" msgid="3918240895519506417"></string>
+ <string name="helper_title_computer" msgid="4671071173916176037">"„Google Play“ paslaugos"</string>
+ <string name="helper_summary_computer" product="default" msgid="467996390095403648">"Naudojant šią paslaugą, telefone esančias nuotraukas, mediją ir pranešimus galima bendrinti su kitais įrenginiais"</string>
+ <string name="helper_summary_computer" product="tablet" msgid="467996390095403648">"Naudojant šią paslaugą, telefone esančias nuotraukas, mediją ir pranešimus galima bendrinti su kitais įrenginiais"</string>
<string name="profile_name_generic" msgid="6851028682723034988">"įrenginys"</string>
<string name="summary_generic" msgid="2346762210105903720"></string>
<string name="consent_yes" msgid="8344487259618762872">"Leisti"</string>
<string name="consent_no" msgid="2640796915611404382">"Neleisti"</string>
+ <string name="consent_ok" msgid="3662376764371001106">"Gerai"</string>
<string name="permission_sync_confirmation_title" msgid="667074294393493186">"Laikrodžio programų perkėlimo leidimai"</string>
<string name="permission_sync_summary" msgid="8873391306499120778">"Kad būtų lengviau nustatyti laikrodį, jame atliekant sąranką įdiegtoms programoms bus naudojami tie patys leidimai kaip jūsų telefone.\n\n Šie leidimai gali apimti prieigą prie laikrodžio mikrofono ir vietovės."</string>
</resources>
diff --git a/packages/CompanionDeviceManager/res/values-lv/strings.xml b/packages/CompanionDeviceManager/res/values-lv/strings.xml
index cabfc77..71bc792 100644
--- a/packages/CompanionDeviceManager/res/values-lv/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-lv/strings.xml
@@ -22,18 +22,30 @@
<string name="chooser_title" msgid="2262294130493605839">"Profila (<xliff:g id="PROFILE_NAME">%1$s</xliff:g>) izvēle, ko pārvaldīt lietotnē <strong><xliff:g id="APP_NAME">%2$s</xliff:g></strong>"</string>
<string name="summary_watch" product="default" msgid="7113724443198337683">"Lietotnei <xliff:g id="APP_NAME">%1$s</xliff:g> tiks atļauts mijiedarboties ar jūsu paziņojumiem un piekļūt šādām atļaujām: Tālrunis, Īsziņas, Kontaktpersonas un Kalendārs."</string>
<string name="summary_watch" product="tablet" msgid="7113724443198337683">"Lietotnei <xliff:g id="APP_NAME">%1$s</xliff:g> tiks atļauts mijiedarboties ar jūsu paziņojumiem un piekļūt šādām atļaujām: Tālrunis, Īsziņas, Kontaktpersonas un Kalendārs."</string>
- <string name="title_app_streaming" msgid="4459136600249308574">"Vai atļaujat lietotnei <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> straumēt lietojumprogrammas?"</string>
+ <string name="permission_apps" msgid="6142133265286656158">"Lietotnes"</string>
+ <string name="permission_apps_summary" msgid="798718816711515431">"Var straumēt jūsu tālruņa lietotnes"</string>
+ <string name="title_app_streaming" msgid="2270331024626446950">"Atļaut lietotnei <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> piekļūt šai informācijai no jūsu tālruņa"</string>
<string name="summary_app_streaming" product="default" msgid="6105916810614498138">"Atļaut lietotnei <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> nodrošināt attālu piekļuvi tālrunim <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong>, lai piekļūtu šajā tālrunī instalētajām lietojumprogrammām, kamēr ir izveidots savienojums."</string>
<string name="summary_app_streaming" product="tablet" msgid="2996373715966272792">"Atļaut lietotnei <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> nodrošināt attālu piekļuvi planšetdatoram <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong>, lai piekļūtu šajā planšetdatorā instalētajām lietojumprogrammām, kamēr ir izveidots savienojums."</string>
<string name="summary_app_streaming" product="device" msgid="7614171699434639963">"Atļaut lietotnei <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> nodrošināt attālu piekļuvi ierīcei <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong>, lai piekļūtu šajā ierīcē instalētajām lietojumprogrammām, kamēr ir izveidots savienojums."</string>
+ <string name="helper_title_app_streaming" msgid="4151687003439969765">"Vairāku ierīču pakalpojumi"</string>
+ <string name="helper_summary_app_streaming" msgid="5344341720432827388">"Šis pakalpojums tiek izmantots, lai straumētu lietotnes jūsu ierīcēs"</string>
<string name="title_automotive_projection" msgid="3296005598978412847"></string>
<string name="summary_automotive_projection" msgid="8683801274662496164"></string>
<string name="title_computer" msgid="4693714143506569253">"Atļaut lietotnei <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> piekļūt šai informācijai no jūsu tālruņa"</string>
<string name="summary_computer" msgid="3798467601598297062"></string>
+ <string name="permission_notification" msgid="693762568127741203">"Paziņojumi"</string>
+ <string name="permission_notification_summary" msgid="4398672775023193663">"Var lasīt visus paziņojumus, tostarp tādu informāciju kā kontaktpersonas, ziņojumus un fotoattēlus"</string>
+ <string name="permission_storage" msgid="6831099350839392343">"Fotoattēli un multivides faili"</string>
+ <string name="permission_storage_summary" msgid="3918240895519506417"></string>
+ <string name="helper_title_computer" msgid="4671071173916176037">"Google Play pakalpojumi"</string>
+ <string name="helper_summary_computer" product="default" msgid="467996390095403648">"Šis pakalpojums kopīgo fotoattēlus, multivides saturu un paziņojumus no jūsu tālruņa citās ierīcēs"</string>
+ <string name="helper_summary_computer" product="tablet" msgid="467996390095403648">"Šis pakalpojums kopīgo fotoattēlus, multivides saturu un paziņojumus no jūsu tālruņa citās ierīcēs"</string>
<string name="profile_name_generic" msgid="6851028682723034988">"ierīce"</string>
<string name="summary_generic" msgid="2346762210105903720"></string>
<string name="consent_yes" msgid="8344487259618762872">"Atļaut"</string>
<string name="consent_no" msgid="2640796915611404382">"Neatļaut"</string>
+ <string name="consent_ok" msgid="3662376764371001106">"Labi"</string>
<string name="permission_sync_confirmation_title" msgid="667074294393493186">"Lietotņu atļauju pārsūtīšana uz pulksteni"</string>
<string name="permission_sync_summary" msgid="8873391306499120778">"Lai atvieglotu pulksteņa iestatīšanu, iestatīšanas laikā pulkstenī instalētās lietotnes saņems tādas pašas atļaujas, kādas tām ir tālrunī.\n\n Tostarp lietotnes var saņemt atļauju piekļūt pulksteņa mikrofonam un atrašanās vietai."</string>
</resources>
diff --git a/packages/CompanionDeviceManager/res/values-mk/strings.xml b/packages/CompanionDeviceManager/res/values-mk/strings.xml
index b4531b5..851651f 100644
--- a/packages/CompanionDeviceManager/res/values-mk/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-mk/strings.xml
@@ -22,18 +22,30 @@
<string name="chooser_title" msgid="2262294130493605839">"Изберете <xliff:g id="PROFILE_NAME">%1$s</xliff:g> со којшто ќе управува <strong><xliff:g id="APP_NAME">%2$s</xliff:g></strong>"</string>
<string name="summary_watch" product="default" msgid="7113724443198337683">"<xliff:g id="APP_NAME">%1$s</xliff:g> ќе може да остварува интеракција со известувањата и да пристапува до дозволите за телефонот, SMS, контактите и календарот."</string>
<string name="summary_watch" product="tablet" msgid="7113724443198337683">"<xliff:g id="APP_NAME">%1$s</xliff:g> ќе може да остварува интеракција со известувањата и да пристапува до дозволите за телефонот, SMS, контактите и календарот."</string>
- <string name="title_app_streaming" msgid="4459136600249308574">"Да се дозволи <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> да стримува апликации?"</string>
+ <string name="permission_apps" msgid="6142133265286656158">"Апликации"</string>
+ <string name="permission_apps_summary" msgid="798718816711515431">"Стримувајте ги апликациите на телефонот"</string>
+ <string name="title_app_streaming" msgid="2270331024626446950">"Овозможете <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> да пристапува до овие податоци на телефонот"</string>
<string name="summary_app_streaming" product="default" msgid="6105916810614498138">"Дозволете <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> да обезбеди далечински пристап на <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong> за да пристапува до апликации инсталирани на телефонов кога ќе се поврзе."</string>
<string name="summary_app_streaming" product="tablet" msgid="2996373715966272792">"Дозволете <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> да обезбеди далечински пристап на <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong> за да пристапува до апликации инсталирани на таблетов кога ќе се поврзе."</string>
<string name="summary_app_streaming" product="device" msgid="7614171699434639963">"Дозволете <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> да обезбеди далечински пристап на <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong> за да пристапува до апликации инсталирани на уредов кога ќе се поврзе."</string>
+ <string name="helper_title_app_streaming" msgid="4151687003439969765">"Повеќенаменски услуги"</string>
+ <string name="helper_summary_app_streaming" msgid="5344341720432827388">"Услугава се користи за стриминг на апликации помеѓу вашите уреди"</string>
<string name="title_automotive_projection" msgid="3296005598978412847"></string>
<string name="summary_automotive_projection" msgid="8683801274662496164"></string>
<string name="title_computer" msgid="4693714143506569253">"Овозможете <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> да пристапува до овие податоци на телефонот"</string>
<string name="summary_computer" msgid="3798467601598297062"></string>
+ <string name="permission_notification" msgid="693762568127741203">"Известувања"</string>
+ <string name="permission_notification_summary" msgid="4398672775023193663">"може да ги чита сите известувања, вклучително и податоци како договори, пораки и фотографии"</string>
+ <string name="permission_storage" msgid="6831099350839392343">"Аудиовизуелни содржини"</string>
+ <string name="permission_storage_summary" msgid="3918240895519506417"></string>
+ <string name="helper_title_computer" msgid="4671071173916176037">"Услуги на Google Play"</string>
+ <string name="helper_summary_computer" product="default" msgid="467996390095403648">"Услугава споделува фотографии, аудиовизуелни содржини и известувања од вашиот телефон на други уреди"</string>
+ <string name="helper_summary_computer" product="tablet" msgid="467996390095403648">"Услугава споделува фотографии, аудиовизуелни содржини и известувања од вашиот телефон на други уреди"</string>
<string name="profile_name_generic" msgid="6851028682723034988">"уред"</string>
<string name="summary_generic" msgid="2346762210105903720"></string>
<string name="consent_yes" msgid="8344487259618762872">"Дозволи"</string>
<string name="consent_no" msgid="2640796915611404382">"Не дозволувај"</string>
+ <string name="consent_ok" msgid="3662376764371001106">"Во ред"</string>
<string name="permission_sync_confirmation_title" msgid="667074294393493186">"Префрлете ги дозволите за апликациите на вашиот часовник"</string>
<string name="permission_sync_summary" msgid="8873391306499120778">"За полесно поставувањето на часовникот, апликациите инсталирани на часовникот при поставувањето ќе ги користат истите дозволи како на телефонот.\n\n Овие дозволи може да опфаќаат пристап до микрофонот и локацијата на часовникот."</string>
</resources>
diff --git a/packages/CompanionDeviceManager/res/values-ml/strings.xml b/packages/CompanionDeviceManager/res/values-ml/strings.xml
index 85952ca..9e330e6 100644
--- a/packages/CompanionDeviceManager/res/values-ml/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-ml/strings.xml
@@ -22,18 +22,30 @@
<string name="chooser_title" msgid="2262294130493605839">"<strong><xliff:g id="APP_NAME">%2$s</xliff:g></strong> ഉപയോഗിച്ച് മാനേജ് ചെയ്യുന്നതിന് ഒരു <xliff:g id="PROFILE_NAME">%1$s</xliff:g> തിരഞ്ഞെടുക്കുക"</string>
<string name="summary_watch" product="default" msgid="7113724443198337683">"നിങ്ങളുടെ അറിയിപ്പുകളുമായി സംവദിക്കാനും നിങ്ങളുടെ ഫോൺ, SMS, കോൺടാക്റ്റുകൾ, കലണ്ടർ അനുമതികൾ എന്നിവ ആക്സസ് ചെയ്യാനും <xliff:g id="APP_NAME">%1$s</xliff:g> എന്നതിനെ അനുവദിക്കും."</string>
<string name="summary_watch" product="tablet" msgid="7113724443198337683">"നിങ്ങളുടെ അറിയിപ്പുകളുമായി സംവദിക്കാനും നിങ്ങളുടെ ഫോൺ, SMS, കോൺടാക്റ്റുകൾ, കലണ്ടർ അനുമതികൾ എന്നിവ ആക്സസ് ചെയ്യാനും <xliff:g id="APP_NAME">%1$s</xliff:g> എന്നതിനെ അനുവദിക്കും."</string>
- <string name="title_app_streaming" msgid="4459136600249308574">"ആപ്പുകൾ സ്ട്രീം ചെയ്യാൻ <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> എന്നതിനെ അനുവദിക്കണോ?"</string>
+ <string name="permission_apps" msgid="6142133265286656158">"ആപ്പുകൾ"</string>
+ <string name="permission_apps_summary" msgid="798718816711515431">"നിങ്ങളുടെ ഫോണിലെ ആപ്പുകൾ സ്ട്രീം ചെയ്യാൻ"</string>
+ <string name="title_app_streaming" msgid="2270331024626446950">"നിങ്ങളുടെ ഫോണിൽ നിന്ന് ഈ വിവരങ്ങൾ ആക്സസ് ചെയ്യാൻ <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> ആപ്പിനെ അനുവദിക്കുക"</string>
<string name="summary_app_streaming" product="default" msgid="6105916810614498138">"കണക്റ്റ് ചെയ്യുമ്പോൾ, ഈ ഫോണിൽ ഇൻസ്റ്റാൾ ചെയ്തിട്ടുള്ള ആപ്പുകൾ ആക്സസ് ചെയ്യാനുള്ള റിമോട്ട് ആക്സസ് <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong> എന്നതിന് നൽകാൻ <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> എന്നതിനെ അനുവദിക്കുക."</string>
<string name="summary_app_streaming" product="tablet" msgid="2996373715966272792">"കണക്റ്റ് ചെയ്യുമ്പോൾ, ഈ ടാബ്ലെറ്റിൽ ഇൻസ്റ്റാൾ ചെയ്തിട്ടുള്ള ആപ്പുകൾ ആക്സസ് ചെയ്യാനുള്ള റിമോട്ട് ആക്സസ് <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong> എന്നതിന് നൽകാൻ <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> എന്നതിനെ അനുവദിക്കുക."</string>
<string name="summary_app_streaming" product="device" msgid="7614171699434639963">"കണക്റ്റ് ചെയ്യുമ്പോൾ, ഈ ഉപകരണത്തിൽ ഇൻസ്റ്റാൾ ചെയ്തിട്ടുള്ള ആപ്പുകൾ ആക്സസ് ചെയ്യാനുള്ള റിമോട്ട് ആക്സസ് <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong> എന്നതിന് നൽകാൻ <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> എന്നതിനെ അനുവദിക്കുക."</string>
+ <string name="helper_title_app_streaming" msgid="4151687003439969765">"ക്രോസ്-ഉപകരണ സേവനങ്ങൾ"</string>
+ <string name="helper_summary_app_streaming" msgid="5344341720432827388">"നിങ്ങളുടെ ഉപകരണങ്ങൾക്കിടയിൽ ആപ്പുകൾ സ്ട്രീം ചെയ്യാൻ ഈ സേവനം ഉപയോഗിക്കുന്നു"</string>
<string name="title_automotive_projection" msgid="3296005598978412847"></string>
<string name="summary_automotive_projection" msgid="8683801274662496164"></string>
<string name="title_computer" msgid="4693714143506569253">"നിങ്ങളുടെ ഫോണിൽ നിന്ന് ഈ വിവരങ്ങൾ ആക്സസ് ചെയ്യാൻ <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> ആപ്പിനെ അനുവദിക്കുക"</string>
<string name="summary_computer" msgid="3798467601598297062"></string>
+ <string name="permission_notification" msgid="693762568127741203">"അറിയിപ്പുകൾ"</string>
+ <string name="permission_notification_summary" msgid="4398672775023193663">"കോൺടാക്റ്റുകൾ, സന്ദേശങ്ങൾ, ഫോട്ടോകൾ എന്നിവ പോലുള്ള വിവരങ്ങൾ ഉൾപ്പെടെ, എല്ലാ അറിയിപ്പുകളും വായിക്കാനാകും"</string>
+ <string name="permission_storage" msgid="6831099350839392343">"ഫോട്ടോകളും മീഡിയയും"</string>
+ <string name="permission_storage_summary" msgid="3918240895519506417"></string>
+ <string name="helper_title_computer" msgid="4671071173916176037">"Google Play സേവനങ്ങൾ"</string>
+ <string name="helper_summary_computer" product="default" msgid="467996390095403648">"ഈ സേവനം നിങ്ങളുടെ ഫോണിൽ നിന്ന് ഫോട്ടോകളും മീഡിയയും അറിയിപ്പുകളും മറ്റ് ഉപകരണങ്ങളിലേക്ക് അയയ്ക്കുന്നു"</string>
+ <string name="helper_summary_computer" product="tablet" msgid="467996390095403648">"ഈ സേവനം നിങ്ങളുടെ ഫോണിൽ നിന്ന് ഫോട്ടോകളും മീഡിയയും അറിയിപ്പുകളും മറ്റ് ഉപകരണങ്ങളിലേക്ക് അയയ്ക്കുന്നു"</string>
<string name="profile_name_generic" msgid="6851028682723034988">"ഉപകരണം"</string>
<string name="summary_generic" msgid="2346762210105903720"></string>
<string name="consent_yes" msgid="8344487259618762872">"അനുവദിക്കുക"</string>
<string name="consent_no" msgid="2640796915611404382">"അനുവദിക്കരുത്"</string>
+ <string name="consent_ok" msgid="3662376764371001106">"ശരി"</string>
<string name="permission_sync_confirmation_title" msgid="667074294393493186">"നിങ്ങളുടെ വാച്ചിലേക്ക് ആപ്പ് അനുമതികൾ കൈമാറുക"</string>
<string name="permission_sync_summary" msgid="8873391306499120778">"നിങ്ങളുടെ വാച്ച് സജ്ജീകരിക്കുന്നത് എളുപ്പമാക്കാൻ, സജ്ജീകരിക്കുമ്പോൾ ഫോണിലുള്ള അതേ അനുമതികൾ നിങ്ങളുടെ വാച്ചിൽ ഇൻസ്റ്റാൾ ചെയ്തിട്ടുള്ള ആപ്പുകൾ ഉപയോഗിക്കും.\n\n ഈ അനുമതികളിൽ നിങ്ങളുടെ വാച്ചിന്റെ മൈക്രോഫോണിലേക്കും ലോക്കേഷനിലേക്കുമുള്ള ആക്സസ് ഉൾപ്പെട്ടേക്കാം."</string>
</resources>
diff --git a/packages/CompanionDeviceManager/res/values-mn/strings.xml b/packages/CompanionDeviceManager/res/values-mn/strings.xml
index c0d589d..00c032d 100644
--- a/packages/CompanionDeviceManager/res/values-mn/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-mn/strings.xml
@@ -22,18 +22,30 @@
<string name="chooser_title" msgid="2262294130493605839">"<strong><xliff:g id="APP_NAME">%2$s</xliff:g></strong>-н удирдах<xliff:g id="PROFILE_NAME">%1$s</xliff:g>-г сонгоно уу"</string>
<string name="summary_watch" product="default" msgid="7113724443198337683">"<xliff:g id="APP_NAME">%1$s</xliff:g>-д таны мэдэгдлүүдтэй харилцаж, таны Утас, SMS, Харилцагчид болон Календарийн зөвшөөрөлд хандахыг зөвшөөрнө."</string>
<string name="summary_watch" product="tablet" msgid="7113724443198337683">"<xliff:g id="APP_NAME">%1$s</xliff:g>-д таны мэдэгдлүүдтэй харилцаж, таны Утас, SMS, Харилцагчид болон Календарийн зөвшөөрөлд хандахыг зөвшөөрнө."</string>
- <string name="title_app_streaming" msgid="4459136600249308574">"<strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong>-д аппуудыг дамжуулахыг зөвшөөрөх үү?"</string>
+ <string name="permission_apps" msgid="6142133265286656158">"Аппууд"</string>
+ <string name="permission_apps_summary" msgid="798718816711515431">"Таны утасны аппуудыг дамжуулах"</string>
+ <string name="title_app_streaming" msgid="2270331024626446950">"<strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong>-д таны утаснаас энэ мэдээлэлд хандахыг зөвшөөрнө үү"</string>
<string name="summary_app_streaming" product="default" msgid="6105916810614498138">"<strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong>-д <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong>-г холбогдсон үед энэ утсанд суулгасан аппуудад хандахын тулд алсын хандалт өгөхийг зөвшөөрнө үү."</string>
<string name="summary_app_streaming" product="tablet" msgid="2996373715966272792">"<strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong>-д <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong>-г холбогдсон үед энэ таблетад суулгасан аппуудад хандахын тулд алсын хандалт өгөхийг зөвшөөрнө үү."</string>
<string name="summary_app_streaming" product="device" msgid="7614171699434639963">"<strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong>-д <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong>-г холбогдсон үед энэ төхөөрөмжид суулгасан аппуудад хандахын тулд алсын хандалт өгөхийг зөвшөөрнө үү."</string>
+ <string name="helper_title_app_streaming" msgid="4151687003439969765">"Төхөөрөмж хоорондын үйлчилгээ"</string>
+ <string name="helper_summary_app_streaming" msgid="5344341720432827388">"Энэ үйлчилгээг таны төхөөрөмжүүд хооронд аппууд дамжуулахад ашигладаг"</string>
<string name="title_automotive_projection" msgid="3296005598978412847"></string>
<string name="summary_automotive_projection" msgid="8683801274662496164"></string>
<string name="title_computer" msgid="4693714143506569253">"<strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong>-д таны утаснаас энэ мэдээлэлд хандахыг зөвшөөрнө үү"</string>
<string name="summary_computer" msgid="3798467601598297062"></string>
+ <string name="permission_notification" msgid="693762568127741203">"Мэдэгдэл"</string>
+ <string name="permission_notification_summary" msgid="4398672775023193663">"Гэрээ, мессеж болон зураг зэрэг мэдээллийг оруулаад бүх мэдэгдлийг унших боломжтой"</string>
+ <string name="permission_storage" msgid="6831099350839392343">"Зураг болон медиа"</string>
+ <string name="permission_storage_summary" msgid="3918240895519506417"></string>
+ <string name="helper_title_computer" msgid="4671071173916176037">"Google Play үйлчилгээ"</string>
+ <string name="helper_summary_computer" product="default" msgid="467996390095403648">"Энэ үйлчилгээ зураг, медиа болон мэдэгдлийг таны утаснаас бусад төхөөрөмж рүү хуваалцана"</string>
+ <string name="helper_summary_computer" product="tablet" msgid="467996390095403648">"Энэ үйлчилгээ зураг, медиа болон мэдэгдлийг таны утаснаас бусад төхөөрөмж рүү хуваалцана"</string>
<string name="profile_name_generic" msgid="6851028682723034988">"төхөөрөмж"</string>
<string name="summary_generic" msgid="2346762210105903720"></string>
<string name="consent_yes" msgid="8344487259618762872">"Зөвшөөрөх"</string>
<string name="consent_no" msgid="2640796915611404382">"Бүү зөвшөөр"</string>
+ <string name="consent_ok" msgid="3662376764371001106">"OK"</string>
<string name="permission_sync_confirmation_title" msgid="667074294393493186">"Цагандаа аппын зөвшөөрлийг шилжүүлэх"</string>
<string name="permission_sync_summary" msgid="8873391306499120778">"Таны цагийг тохируулахад илүү хялбар болгохын тулд тохируулгын үеэр таны цаган дээр суулгасан аппууд нь утастай тань ижил зөвшөөрлийг ашиглана.\n\n Эдгээр зөвшөөрөлд таны цагийн микрофон болон байршлын хандалт зэрэг багтаж магадгүй."</string>
</resources>
diff --git a/packages/CompanionDeviceManager/res/values-mr/strings.xml b/packages/CompanionDeviceManager/res/values-mr/strings.xml
index 0ce6ab7..303b141 100644
--- a/packages/CompanionDeviceManager/res/values-mr/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-mr/strings.xml
@@ -22,18 +22,30 @@
<string name="chooser_title" msgid="2262294130493605839">"<strong><xliff:g id="APP_NAME">%2$s</xliff:g></strong> द्वारे व्यवस्थापित करण्यासाठी <xliff:g id="PROFILE_NAME">%1$s</xliff:g> निवडा"</string>
<string name="summary_watch" product="default" msgid="7113724443198337683">"<xliff:g id="APP_NAME">%1$s</xliff:g> ला तुमच्या सूचनांशी संवाद साधण्याची आणि तुमचा फोन, एसएमएस, संपर्क आणि Calendar च्या परवानग्या अॅक्सेस करण्याची अनुमती मिळेल."</string>
<string name="summary_watch" product="tablet" msgid="7113724443198337683">"<xliff:g id="APP_NAME">%1$s</xliff:g> ला तुमच्या सूचनांशी संवाद साधण्याची आणि तुमचा फोन, एसएमएस, संपर्क आणि Calendar च्या परवानग्या अॅक्सेस करण्याची अनुमती मिळेल."</string>
- <string name="title_app_streaming" msgid="4459136600249308574">"<strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> ला अॅप्लिकेशन स्ट्रीम करण्याची अनुमती द्यायची आहे का?"</string>
+ <string name="permission_apps" msgid="6142133265286656158">"ॲप्स"</string>
+ <string name="permission_apps_summary" msgid="798718816711515431">"फोनवरील ॲप्स स्ट्रीम करा"</string>
+ <string name="title_app_streaming" msgid="2270331024626446950">"<strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> ला ही माहिती तुमच्या फोनवरून अॅक्सेस करण्यासाठी अनुमती द्या"</string>
<string name="summary_app_streaming" product="default" msgid="6105916810614498138">"कनेक्ट केलेले असताना या फोनवरील अॅप्लिकेशन अॅक्सेस करता यावीत यासाठी <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> ला <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong> चा रिमोट अॅक्सेस द्या."</string>
<string name="summary_app_streaming" product="tablet" msgid="2996373715966272792">"कनेक्ट केलेले असताना या टॅबलेटवरील अॅप्लिकेशन अॅक्सेस करता यावीत यासाठी <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> ला <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong> चा रिमोट अॅक्सेस द्या."</string>
<string name="summary_app_streaming" product="device" msgid="7614171699434639963">"कनेक्ट केलेले असताना या डिव्हाइसवरील अॅप्लिकेशन अॅक्सेस करता यावीत यासाठी <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> ला <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong> चा रिमोट अॅक्सेस द्या."</string>
+ <string name="helper_title_app_streaming" msgid="4151687003439969765">"क्रॉस-डिव्हाइस सेवा"</string>
+ <string name="helper_summary_app_streaming" msgid="5344341720432827388">"ही सेवा तुमच्या डिव्हाइस दरम्यान अॅप्स स्ट्रीम करण्यासाठी वापरली जाते"</string>
<string name="title_automotive_projection" msgid="3296005598978412847"></string>
<string name="summary_automotive_projection" msgid="8683801274662496164"></string>
<string name="title_computer" msgid="4693714143506569253">"<strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> ला ही माहिती तुमच्या फोनवरून अॅक्सेस करण्यासाठी अनुमती द्या"</string>
<string name="summary_computer" msgid="3798467601598297062"></string>
+ <string name="permission_notification" msgid="693762568127741203">"सूचना"</string>
+ <string name="permission_notification_summary" msgid="4398672775023193663">"करार, मेसेज आणि फोटो यांसारख्या माहितीच्या समावेशासह सर्व सूचना वाचू शकते"</string>
+ <string name="permission_storage" msgid="6831099350839392343">"फोटो आणि मीडिया"</string>
+ <string name="permission_storage_summary" msgid="3918240895519506417"></string>
+ <string name="helper_title_computer" msgid="4671071173916176037">"Google Play सेवा"</string>
+ <string name="helper_summary_computer" product="default" msgid="467996390095403648">"ही सेवा तुमच्या फोनवरून इतर डिव्हाइसवर फोटो, मीडिया आणि सूचना शेअर करते"</string>
+ <string name="helper_summary_computer" product="tablet" msgid="467996390095403648">"ही सेवा तुमच्या फोनवरून इतर डिव्हाइसवर फोटो, मीडिया आणि सूचना शेअर करते"</string>
<string name="profile_name_generic" msgid="6851028682723034988">"डिव्हाइस"</string>
<string name="summary_generic" msgid="2346762210105903720"></string>
<string name="consent_yes" msgid="8344487259618762872">"अनुमती द्या"</string>
<string name="consent_no" msgid="2640796915611404382">"अनुमती देऊ नका"</string>
+ <string name="consent_ok" msgid="3662376764371001106">"ओके"</string>
<string name="permission_sync_confirmation_title" msgid="667074294393493186">"अॅप परवानग्या तुमच्या वॉचवर ट्रान्सफर करा"</string>
<string name="permission_sync_summary" msgid="8873391306499120778">"तुमचे वॉच सेट करणे आणखी सोपे करण्यासाठी, सेटअपदरम्यान तुमच्या वॉचवर इंस्टॉल केलेली ॲप्स ही तुमच्या फोनप्रमाणेच परवानग्या वापरतील.\n\n या परवानग्यांमध्ये तुमच्या वॉचचा मायक्रोफोन आणि स्थानाच्या अॅक्सेसचा समावेश असू शकतो."</string>
</resources>
diff --git a/packages/CompanionDeviceManager/res/values-ms/strings.xml b/packages/CompanionDeviceManager/res/values-ms/strings.xml
index 2ca8128..e234089 100644
--- a/packages/CompanionDeviceManager/res/values-ms/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-ms/strings.xml
@@ -22,18 +22,30 @@
<string name="chooser_title" msgid="2262294130493605839">"Pilih <xliff:g id="PROFILE_NAME">%1$s</xliff:g> untuk diurus oleh <strong><xliff:g id="APP_NAME">%2$s</xliff:g></strong>"</string>
<string name="summary_watch" product="default" msgid="7113724443198337683">"<xliff:g id="APP_NAME">%1$s</xliff:g> akan dibenarkan berinteraksi dengan pemberitahuan anda dan mengakses kebenaran Telefon, SMS, Kenalan dan Kalendar anda."</string>
<string name="summary_watch" product="tablet" msgid="7113724443198337683">"<xliff:g id="APP_NAME">%1$s</xliff:g> akan dibenarkan berinteraksi dengan pemberitahuan anda dan mengakses kebenaran Telefon, SMS, Kenalan dan Kalendar anda."</string>
- <string name="title_app_streaming" msgid="4459136600249308574">"Benarkan <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> menstrim aplikasi?"</string>
+ <string name="permission_apps" msgid="6142133265286656158">"Apl"</string>
+ <string name="permission_apps_summary" msgid="798718816711515431">"Strim apl telefon anda"</string>
+ <string name="title_app_streaming" msgid="2270331024626446950">"Benarkan <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> mengakses maklumat ini daripada telefon anda"</string>
<string name="summary_app_streaming" product="default" msgid="6105916810614498138">"Membenarkan <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> memberi akses jauh kepada <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong> untuk mengakses aplikasi yang dipasang pada telefon ini apabila disambungkan."</string>
<string name="summary_app_streaming" product="tablet" msgid="2996373715966272792">"Membenarkan <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> memberi akses jauh kepada <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong> untuk mengakses aplikasi yang dipasang pada tablet ini apabila disambungkan."</string>
<string name="summary_app_streaming" product="device" msgid="7614171699434639963">"Membenarkan <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> memberi akses jauh kepada <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong> untuk mengakses aplikasi yang dipasang pada peranti ini apabila disambungkan."</string>
+ <string name="helper_title_app_streaming" msgid="4151687003439969765">"Perkhidmatan silang peranti"</string>
+ <string name="helper_summary_app_streaming" msgid="5344341720432827388">"Perkhidmatan ini digunakan untuk menstrim apl antara peranti anda"</string>
<string name="title_automotive_projection" msgid="3296005598978412847"></string>
<string name="summary_automotive_projection" msgid="8683801274662496164"></string>
<string name="title_computer" msgid="4693714143506569253">"Benarkan <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> untuk mengakses maklumat ini daripada telefon anda"</string>
<string name="summary_computer" msgid="3798467601598297062"></string>
+ <string name="permission_notification" msgid="693762568127741203">"Pemberitahuan"</string>
+ <string name="permission_notification_summary" msgid="4398672775023193663">"Boleh membaca semua pemberitahuan, termasuk maklumat seperti kenalan, mesej dan foto"</string>
+ <string name="permission_storage" msgid="6831099350839392343">"Foto dan media"</string>
+ <string name="permission_storage_summary" msgid="3918240895519506417"></string>
+ <string name="helper_title_computer" msgid="4671071173916176037">"Perkhidmatan Google Play"</string>
+ <string name="helper_summary_computer" product="default" msgid="467996390095403648">"Perkhidmatan ini berkongsi foto, media dan pemberitahuan daripada telefon anda kepada peranti lain"</string>
+ <string name="helper_summary_computer" product="tablet" msgid="467996390095403648">"Perkhidmatan ini berkongsi foto, media dan pemberitahuan daripada telefon anda kepada peranti lain"</string>
<string name="profile_name_generic" msgid="6851028682723034988">"peranti"</string>
<string name="summary_generic" msgid="2346762210105903720"></string>
<string name="consent_yes" msgid="8344487259618762872">"Benarkan"</string>
<string name="consent_no" msgid="2640796915611404382">"Jangan benarkan"</string>
+ <string name="consent_ok" msgid="3662376764371001106">"OK"</string>
<string name="permission_sync_confirmation_title" msgid="667074294393493186">"Pindahkan kebenaran apl pada jam tangan anda"</string>
<string name="permission_sync_summary" msgid="8873391306499120778">"Untuk memudahkan penyediaan jam tangan anda, apl yang dipasang pada jam tangan anda semasa persediaan akan menggunakan kebenaran yang sama seperti telefon anda.\n\n Kebenaran ini mungkin termasuk akses kepada mikrofon dan lokasi jam tangan anda."</string>
</resources>
diff --git a/packages/CompanionDeviceManager/res/values-my/strings.xml b/packages/CompanionDeviceManager/res/values-my/strings.xml
index 1fb20bf..61a60b2 100644
--- a/packages/CompanionDeviceManager/res/values-my/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-my/strings.xml
@@ -22,18 +22,30 @@
<string name="chooser_title" msgid="2262294130493605839">"<strong><xliff:g id="APP_NAME">%2$s</xliff:g></strong> က စီမံခန့်ခွဲရန် <xliff:g id="PROFILE_NAME">%1$s</xliff:g> ကို ရွေးချယ်ပါ"</string>
<string name="summary_watch" product="default" msgid="7113724443198337683">"သင်၏ ‘ဖုန်း’၊ ‘SMS စာတိုစနစ်’၊ ‘အဆက်အသွယ်များ’ နှင့် ‘ပြက္ခဒိန်’ ခွင့်ပြုချက်များကို သုံးရန်နှင့် အကြောင်းကြားချက်များကို ပြန်လှန်တုံ့ပြန်ရန် <xliff:g id="APP_NAME">%1$s</xliff:g> အား ခွင့်ပြုပါမည်။"</string>
<string name="summary_watch" product="tablet" msgid="7113724443198337683">"သင်၏ ‘ဖုန်း’၊ ‘SMS စာတိုစနစ်’၊ ‘အဆက်အသွယ်များ’ နှင့် ‘ပြက္ခဒိန်’ ခွင့်ပြုချက်များကို သုံးရန်နှင့် အကြောင်းကြားချက်များကို ပြန်လှန်တုံ့ပြန်ရန် <xliff:g id="APP_NAME">%1$s</xliff:g> အား ခွင့်ပြုပါမည်။"</string>
- <string name="title_app_streaming" msgid="4459136600249308574">"အပလီကေးရှင်းများကို တိုက်ရိုက်လွှင့်ရန် <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> ကိုခွင့်ပြုမလား။"</string>
+ <string name="permission_apps" msgid="6142133265286656158">"အက်ပ်များ"</string>
+ <string name="permission_apps_summary" msgid="798718816711515431">"သင့်ဖုန်းရှိအက်ပ်များကို တိုက်ရိုက်လွှင့်နိုင်သည်"</string>
+ <string name="title_app_streaming" msgid="2270331024626446950">"<strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> ကို သင့်ဖုန်းမှ ဤအချက်အလက် သုံးခွင့်ပြုမည်"</string>
<string name="summary_app_streaming" product="default" msgid="6105916810614498138">"ချိတ်ဆက်ထားသည့်အခါ ဤဖုန်းတွင် ထည့်သွင်းထားသော အပလီကေးရှင်းများကို သုံးခွင့်ရရန်အတွက် <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong> ကိုအဝေးမှ သုံးခွင့်ပေးနိုင်ရန် <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> အားခွင့်ပြုပါ။"</string>
<string name="summary_app_streaming" product="tablet" msgid="2996373715966272792">"ချိတ်ဆက်ထားသည့်အခါ ဤတက်ဘလက်တွင် ထည့်သွင်းထားသော အပလီကေးရှင်းများကို သုံးခွင့်ရရန်အတွက် <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong> ကိုအဝေးမှ သုံးခွင့်ပေးနိုင်ရန် <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> အားခွင့်ပြုပါ။"</string>
<string name="summary_app_streaming" product="device" msgid="7614171699434639963">"ချိတ်ဆက်ထားသည့်အခါ ဤစက်တွင် ထည့်သွင်းထားသော အပလီကေးရှင်းများကို သုံးခွင့်ရရန်အတွက် <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong> ကိုအဝေးမှ သုံးခွင့်ပေးနိုင်ရန် <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> အားခွင့်ပြုပါ။"</string>
+ <string name="helper_title_app_streaming" msgid="4151687003439969765">"စက်များကြားသုံး ဝန်ဆောင်မှုများ"</string>
+ <string name="helper_summary_app_streaming" msgid="5344341720432827388">"သင့်စက်များကြား အက်ပ်များ တိုက်ရိုက်လွှင့်ရန် ဤဝန်ဆောင်မှုကို အသုံးပြုသည်"</string>
<string name="title_automotive_projection" msgid="3296005598978412847"></string>
<string name="summary_automotive_projection" msgid="8683801274662496164"></string>
<string name="title_computer" msgid="4693714143506569253">"<strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> ကို သင့်ဖုန်းမှ ဤအချက်အလက် သုံးခွင့်ပြုမည်"</string>
<string name="summary_computer" msgid="3798467601598297062"></string>
+ <string name="permission_notification" msgid="693762568127741203">"အကြောင်းကြားချက်များ"</string>
+ <string name="permission_notification_summary" msgid="4398672775023193663">"အဆက်အသွယ်၊ မက်ဆေ့ဂျ်နှင့် ဓာတ်ပုံကဲ့သို့ အချက်အလက်များအပါအဝင် အကြောင်းကြားချက်အားလုံးကို ဖတ်နိုင်သည်"</string>
+ <string name="permission_storage" msgid="6831099350839392343">"ဓာတ်ပုံနှင့် မီဒီယာများ"</string>
+ <string name="permission_storage_summary" msgid="3918240895519506417"></string>
+ <string name="helper_title_computer" msgid="4671071173916176037">"Google Play ဝန်ဆောင်မှုများ"</string>
+ <string name="helper_summary_computer" product="default" msgid="467996390095403648">"ဤဝန်ဆောင်မှုသည် ဓာတ်ပုံ၊ မီဒီယာနှင့် အကြောင်းကြားချက်များကို သင့်ဖုန်းမှ အခြားစက်များသို့ မျှဝေသည်"</string>
+ <string name="helper_summary_computer" product="tablet" msgid="467996390095403648">"ဤဝန်ဆောင်မှုသည် ဓာတ်ပုံ၊ မီဒီယာနှင့် အကြောင်းကြားချက်များကို သင့်ဖုန်းမှ အခြားစက်များသို့ မျှဝေသည်"</string>
<string name="profile_name_generic" msgid="6851028682723034988">"စက်"</string>
<string name="summary_generic" msgid="2346762210105903720"></string>
<string name="consent_yes" msgid="8344487259618762872">"ခွင့်ပြုရန်"</string>
<string name="consent_no" msgid="2640796915611404382">"ခွင့်မပြုပါ"</string>
+ <string name="consent_ok" msgid="3662376764371001106">"OK"</string>
<string name="permission_sync_confirmation_title" msgid="667074294393493186">"သင်၏နာရီသို့ အက်ပ်ခွင့်ပြုချက်များ လွှဲပြောင်းရန်"</string>
<string name="permission_sync_summary" msgid="8873391306499120778">"သင်၏နာရီ စနစ်ထည့်သွင်းရာတွင် ပိုလွယ်ကူစေရန် စနစ်ထည့်သွင်းနေစဉ်အတွင်း နာရီတွင်ထည့်သွင်းသော အက်ပ်များသည် သင့်ဖုန်းနှင့် အလားတူခွင့်ပြုချက်များကို သုံးပါမည်။\n\n ဤခွင့်ပြုချက်များတွင် သင့်နာရီ၏ မိုက်ခရိုဖုန်းနှင့် တည်နေရာတို့ကို သုံးခွင့် ပါဝင်နိုင်သည်။"</string>
</resources>
diff --git a/packages/CompanionDeviceManager/res/values-nb/strings.xml b/packages/CompanionDeviceManager/res/values-nb/strings.xml
index aa73f5d..078a2d4 100644
--- a/packages/CompanionDeviceManager/res/values-nb/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-nb/strings.xml
@@ -22,18 +22,30 @@
<string name="chooser_title" msgid="2262294130493605839">"Velg <xliff:g id="PROFILE_NAME">%1$s</xliff:g> som skal administreres av <strong><xliff:g id="APP_NAME">%2$s</xliff:g></strong>"</string>
<string name="summary_watch" product="default" msgid="7113724443198337683">"<xliff:g id="APP_NAME">%1$s</xliff:g> får tillatelse til å samhandle med varslene dine og får tilgang til Telefon, SMS, kontakter og Kalender."</string>
<string name="summary_watch" product="tablet" msgid="7113724443198337683">"<xliff:g id="APP_NAME">%1$s</xliff:g> får tillatelse til å samhandle med varslene dine og får tilgang til Telefon, SMS, kontakter og Kalender."</string>
- <string name="title_app_streaming" msgid="4459136600249308574">"Vil du gi <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> tillatelse til å strømme apper?"</string>
+ <string name="permission_apps" msgid="6142133265286656158">"Apper"</string>
+ <string name="permission_apps_summary" msgid="798718816711515431">"Strøm appene på telefonen"</string>
+ <string name="title_app_streaming" msgid="2270331024626446950">"Gi <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> tilgang til denne informasjonen fra telefonen din"</string>
<string name="summary_app_streaming" product="default" msgid="6105916810614498138">"Tillat at <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> gir <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong> ekstern tilgang til apper som er installert på denne telefonen, når den er koblet til internett."</string>
<string name="summary_app_streaming" product="tablet" msgid="2996373715966272792">"Tillat at <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> gir <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong> ekstern tilgang til apper som er installert på dette nettbrettet, når det er koblet til internett."</string>
<string name="summary_app_streaming" product="device" msgid="7614171699434639963">"Tillat at <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> gir <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong> ekstern tilgang til apper som er installert på denne enheten, når den er koblet til internett."</string>
+ <string name="helper_title_app_streaming" msgid="4151687003439969765">"Tjenester på flere enheter"</string>
+ <string name="helper_summary_app_streaming" msgid="5344341720432827388">"Denne tjenesten brukes til å strømme apper mellom enhetene dine"</string>
<string name="title_automotive_projection" msgid="3296005598978412847"></string>
<string name="summary_automotive_projection" msgid="8683801274662496164"></string>
<string name="title_computer" msgid="4693714143506569253">"Gi <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> tilgang til denne informasjonen fra telefonen din"</string>
<string name="summary_computer" msgid="3798467601598297062"></string>
+ <string name="permission_notification" msgid="693762568127741203">"Varsler"</string>
+ <string name="permission_notification_summary" msgid="4398672775023193663">"Kan lese alle varsler, inkludert informasjon som kontrakter, meldinger og bilder"</string>
+ <string name="permission_storage" msgid="6831099350839392343">"Bilder og medier"</string>
+ <string name="permission_storage_summary" msgid="3918240895519506417"></string>
+ <string name="helper_title_computer" msgid="4671071173916176037">"Google Play-tjenester"</string>
+ <string name="helper_summary_computer" product="default" msgid="467996390095403648">"Denne tjenesten deler bilder, medier og varsler fra telefonen din til andre enheter"</string>
+ <string name="helper_summary_computer" product="tablet" msgid="467996390095403648">"Denne tjenesten deler bilder, medier og varsler fra telefonen din til andre enheter"</string>
<string name="profile_name_generic" msgid="6851028682723034988">"enhet"</string>
<string name="summary_generic" msgid="2346762210105903720"></string>
<string name="consent_yes" msgid="8344487259618762872">"Tillat"</string>
<string name="consent_no" msgid="2640796915611404382">"Ikke tillat"</string>
+ <string name="consent_ok" msgid="3662376764371001106">"OK"</string>
<string name="permission_sync_confirmation_title" msgid="667074294393493186">"Overfør apptillatelser til klokken din"</string>
<string name="permission_sync_summary" msgid="8873391306499120778">"For å gjøre det enklere å konfigurere klokken din bruker apper som installeres på klokken under konfigureringen, samme tillatelser som på telefonen.\n\n Disse tillatelsene kan inkludere tilgang til mikrofonen på klokken og posisjon."</string>
</resources>
diff --git a/packages/CompanionDeviceManager/res/values-ne/strings.xml b/packages/CompanionDeviceManager/res/values-ne/strings.xml
index 3ba75eb..fd8a6cf 100644
--- a/packages/CompanionDeviceManager/res/values-ne/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-ne/strings.xml
@@ -22,18 +22,30 @@
<string name="chooser_title" msgid="2262294130493605839">"आफूले <strong><xliff:g id="APP_NAME">%2$s</xliff:g></strong> प्रयोग गरी व्यवस्थापन गर्न चाहेको <xliff:g id="PROFILE_NAME">%1$s</xliff:g> चयन गर्नुहोस्"</string>
<string name="summary_watch" product="default" msgid="7113724443198337683">"<xliff:g id="APP_NAME">%1$s</xliff:g> लाई तपाईंका सूचना हेर्ने र फोन, SMS, कन्ट्याक्ट तथा पात्रोसम्बन्धी अनुमतिहरू हेर्ने तथा प्रयोग गर्ने अनुमति दिइने छ।"</string>
<string name="summary_watch" product="tablet" msgid="7113724443198337683">"<xliff:g id="APP_NAME">%1$s</xliff:g> लाई तपाईंका सूचना हेर्ने र फोन, SMS, कन्ट्याक्ट तथा पात्रोसम्बन्धी अनुमतिहरू हेर्ने तथा प्रयोग गर्ने अनुमति दिइने छ।"</string>
- <string name="title_app_streaming" msgid="4459136600249308574">"<strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> लाई एपहरू स्ट्रिम गर्ने अनुमति दिने हो?"</string>
+ <string name="permission_apps" msgid="6142133265286656158">"एपहरू"</string>
+ <string name="permission_apps_summary" msgid="798718816711515431">"आफ्नो फोनका एपहरू प्रयोग गर्नुहोस्"</string>
+ <string name="title_app_streaming" msgid="2270331024626446950">"<strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> लाई तपाईंको फोनमा भएको यो जानकारी हेर्ने तथा प्रयोग गर्ने अनुमति दिनुहोस्"</string>
<string name="summary_app_streaming" product="default" msgid="6105916810614498138">"यो डिभाइस इन्टरनेटमा कनेक्ट भएका बेला, <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong>लाई <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong> लाई यो फोनमा इन्स्टल गरिएका एप टाढैबाट प्रयोग गर्ने अनुमति दिन दिनुहोस्।"</string>
<string name="summary_app_streaming" product="tablet" msgid="2996373715966272792">"यो डिभाइस इन्टरनेटमा कनेक्ट भएका बेला, <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong>लाई <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong> लाई यो ट्याब्लेटमा इन्स्टल गरिएका एप टाढैबाट प्रयोग गर्ने अनुमति दिन दिनुहोस्।"</string>
<string name="summary_app_streaming" product="device" msgid="7614171699434639963">"यो डिभाइस इन्टरनेटमा कनेक्ट भएका बेला, <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> लाई <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong> लाई यो डिभाइसमा इन्स्टल गरिएका एप टाढैबाट प्रयोग गर्ने अनुमति दिन दिनुहोस्।"</string>
+ <string name="helper_title_app_streaming" msgid="4151687003439969765">"क्रस-डिभाइस सेवाहरू"</string>
+ <string name="helper_summary_app_streaming" msgid="5344341720432827388">"यो सेवा तपाईंको एउटा डिभाइसबाट अर्को डिभाइसमा एपहरू स्ट्रिम गर्न प्रयोग गरिन्छ"</string>
<string name="title_automotive_projection" msgid="3296005598978412847"></string>
<string name="summary_automotive_projection" msgid="8683801274662496164"></string>
<string name="title_computer" msgid="4693714143506569253">"<strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> लाई तपाईंको फोनमा भएको यो जानकारी हेर्ने तथा प्रयोग गर्ने अनुमति दिनुहोस्"</string>
<string name="summary_computer" msgid="3798467601598297062"></string>
+ <string name="permission_notification" msgid="693762568127741203">"सूचनाहरू"</string>
+ <string name="permission_notification_summary" msgid="4398672775023193663">"कन्ट्याक्ट, म्यासेज र फोटोलगायतका व्यक्तिगत जानकारीसहित तपाईंका सूचनाहरू पढ्न सक्छ"</string>
+ <string name="permission_storage" msgid="6831099350839392343">"फोटो र मिडिया"</string>
+ <string name="permission_storage_summary" msgid="3918240895519506417"></string>
+ <string name="helper_title_computer" msgid="4671071173916176037">"Google Play services"</string>
+ <string name="helper_summary_computer" product="default" msgid="467996390095403648">"यो सेवाले तपाईंको फोनबाट अन्य डिभाइसमा फोटो, मिडिया र सूचनाहरू सेयर गर्छ"</string>
+ <string name="helper_summary_computer" product="tablet" msgid="467996390095403648">"यो सेवाले तपाईंको फोनबाट अन्य डिभाइसमा फोटो, मिडिया र सूचनाहरू सेयर गर्छ"</string>
<string name="profile_name_generic" msgid="6851028682723034988">"यन्त्र"</string>
<string name="summary_generic" msgid="2346762210105903720"></string>
<string name="consent_yes" msgid="8344487259618762872">"अनुमति दिनुहोस्"</string>
<string name="consent_no" msgid="2640796915611404382">"अनुमति नदिनुहोस्"</string>
+ <string name="consent_ok" msgid="3662376764371001106">"ठिक छ"</string>
<string name="permission_sync_confirmation_title" msgid="667074294393493186">"एपलाई दिइएका अनुमति घडीमा ट्रान्स्फर गर्नुहोस्"</string>
<string name="permission_sync_summary" msgid="8873391306499120778">"तपाईंको घडी सेटअप गर्ने कार्य सजिलो बनाउनका लागि सेटअप गर्ने क्रममा तपाईंको घडीमा इन्स्टल गरिएका एपहरूले पनि तपाईंको फोनमा दिइएको जस्तै अनुमति प्रयोग गर्ने छन्।\n\n यी अनुमतिमा तपाईंको घडीको माइक्रोफोन र लोकेसन प्रयोग गर्ने जस्ता अनुमति पर्न सक्छन्।"</string>
</resources>
diff --git a/packages/CompanionDeviceManager/res/values-nl/strings.xml b/packages/CompanionDeviceManager/res/values-nl/strings.xml
index bc09a58..76ec957 100644
--- a/packages/CompanionDeviceManager/res/values-nl/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-nl/strings.xml
@@ -22,18 +22,30 @@
<string name="chooser_title" msgid="2262294130493605839">"Een <xliff:g id="PROFILE_NAME">%1$s</xliff:g> kiezen om te beheren met <strong><xliff:g id="APP_NAME">%2$s</xliff:g></strong>"</string>
<string name="summary_watch" product="default" msgid="7113724443198337683">"<xliff:g id="APP_NAME">%1$s</xliff:g> kan interactie hebben met je meldingen en toegang krijgen tot je rechten voor telefoon, sms, contacten en agenda."</string>
<string name="summary_watch" product="tablet" msgid="7113724443198337683">"<xliff:g id="APP_NAME">%1$s</xliff:g> kan interactie hebben met je meldingen en toegang krijgen tot je rechten voor telefoon, sms, contacten en agenda."</string>
- <string name="title_app_streaming" msgid="4459136600249308574">"Toestaan dat <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> apps streamt?"</string>
+ <string name="permission_apps" msgid="6142133265286656158">"Apps"</string>
+ <string name="permission_apps_summary" msgid="798718816711515431">"De apps van je telefoon streamen"</string>
+ <string name="title_app_streaming" msgid="2270331024626446950">"<strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> toegang geven tot deze informatie op je telefoon"</string>
<string name="summary_app_streaming" product="default" msgid="6105916810614498138">"Toestaan dat <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> als er verbinding is <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong> externe toegang geeft tot apps die zijn geïnstalleerd op deze telefoon."</string>
<string name="summary_app_streaming" product="tablet" msgid="2996373715966272792">"Toestaan dat <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> als er verbinding is <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong> externe toegang geeft tot apps die zijn geïnstalleerd op deze tablet."</string>
<string name="summary_app_streaming" product="device" msgid="7614171699434639963">"Toestaan dat <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> als er verbinding is <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong> externe toegang geeft tot apps die zijn geïnstalleerd op dit apparaat."</string>
+ <string name="helper_title_app_streaming" msgid="4151687003439969765">"Cross-device-services"</string>
+ <string name="helper_summary_app_streaming" msgid="5344341720432827388">"Met deze service kun je apps streamen tussen je apparaten"</string>
<string name="title_automotive_projection" msgid="3296005598978412847"></string>
<string name="summary_automotive_projection" msgid="8683801274662496164"></string>
<string name="title_computer" msgid="4693714143506569253">"<strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> toegang geven tot deze informatie op je telefoon"</string>
<string name="summary_computer" msgid="3798467601598297062"></string>
+ <string name="permission_notification" msgid="693762568127741203">"Meldingen"</string>
+ <string name="permission_notification_summary" msgid="4398672775023193663">"Kan alle meldingen lezen, waaronder informatie zoals contacten, berichten en foto\'s"</string>
+ <string name="permission_storage" msgid="6831099350839392343">"Foto\'s en media"</string>
+ <string name="permission_storage_summary" msgid="3918240895519506417"></string>
+ <string name="helper_title_computer" msgid="4671071173916176037">"Google Play-services"</string>
+ <string name="helper_summary_computer" product="default" msgid="467996390095403648">"Met deze service kun je foto\'s, media en meldingen vanaf je telefoon met andere apparaten delen"</string>
+ <string name="helper_summary_computer" product="tablet" msgid="467996390095403648">"Met deze service kun je foto\'s, media en meldingen vanaf je telefoon met andere apparaten delen"</string>
<string name="profile_name_generic" msgid="6851028682723034988">"apparaat"</string>
<string name="summary_generic" msgid="2346762210105903720"></string>
<string name="consent_yes" msgid="8344487259618762872">"Toestaan"</string>
<string name="consent_no" msgid="2640796915611404382">"Niet toestaan"</string>
+ <string name="consent_ok" msgid="3662376764371001106">"OK"</string>
<string name="permission_sync_confirmation_title" msgid="667074294393493186">"App-rechten overzetten naar je horloge"</string>
<string name="permission_sync_summary" msgid="8873391306499120778">"We willen het makkelijker voor je maken om je horloge in te stellen. Daarom gebruiken apps die tijdens het instellen worden geïnstalleerd op je horloge, dezelfde rechten als op je telefoon.\n\n Deze rechten kunnen toegang tot de microfoon en locatie van je horloge omvatten."</string>
</resources>
diff --git a/packages/CompanionDeviceManager/res/values-or/strings.xml b/packages/CompanionDeviceManager/res/values-or/strings.xml
index 92d0a5ef..6b66492 100644
--- a/packages/CompanionDeviceManager/res/values-or/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-or/strings.xml
@@ -22,18 +22,30 @@
<string name="chooser_title" msgid="2262294130493605839">"<strong><xliff:g id="APP_NAME">%2$s</xliff:g></strong> ଦ୍ୱାରା ପରିଚାଳିତ ହେବା ପାଇଁ ଏକ <xliff:g id="PROFILE_NAME">%1$s</xliff:g>କୁ ବାଛନ୍ତୁ"</string>
<string name="summary_watch" product="default" msgid="7113724443198337683">"ଆପଣଙ୍କ ବିଜ୍ଞପ୍ତିଗୁଡ଼ିକ ସହ ଇଣ୍ଟରାକ୍ଟ କରିବା ଏବଂ ଆପଣଙ୍କ ଫୋନ, SMS, ଯୋଗାଯୋଗ ଓ କ୍ୟାଲେଣ୍ଡର ଅନୁମତିଗୁଡ଼ିକୁ ଆକ୍ସେସ କରିବା ପାଇଁ <xliff:g id="APP_NAME">%1$s</xliff:g>କୁ ଅନୁମତି ଦିଆଯିବ।"</string>
<string name="summary_watch" product="tablet" msgid="7113724443198337683">"ଆପଣଙ୍କ ବିଜ୍ଞପ୍ତିଗୁଡ଼ିକ ସହ ଇଣ୍ଟରାକ୍ଟ କରିବା ଏବଂ ଆପଣଙ୍କ ଫୋନ, SMS, ଯୋଗାଯୋଗ ଓ କ୍ୟାଲେଣ୍ଡର ଅନୁମତିଗୁଡ଼ିକୁ ଆକ୍ସେସ କରିବା ପାଇଁ <xliff:g id="APP_NAME">%1$s</xliff:g>କୁ ଅନୁମତି ଦିଆଯିବ।"</string>
- <string name="title_app_streaming" msgid="4459136600249308574">"<strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong>କୁ ଆପ୍ଲିକେସନଗୁଡ଼ିକ ଷ୍ଟ୍ରିମ କରିବା ପାଇଁ ଅନୁମତି ଦେବେ କି?"</string>
+ <string name="permission_apps" msgid="6142133265286656158">"ଆପ୍ସ"</string>
+ <string name="permission_apps_summary" msgid="798718816711515431">"ଆପଣଙ୍କ ଫୋନର ଆପ୍ସକୁ ଷ୍ଟ୍ରିମ କରନ୍ତୁ"</string>
+ <string name="title_app_streaming" msgid="2270331024626446950">"ଆପଣଙ୍କ ଫୋନରୁ ଏହି ସୂଚନାକୁ ଆକ୍ସେସ କରିବା ପାଇଁ <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong>କୁ ଅନୁମତି ଦିଅନ୍ତୁ"</string>
<string name="summary_app_streaming" product="default" msgid="6105916810614498138">"<strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong>କୁ, ଏହି ଫୋନଟି ସଂଯୁକ୍ତ ହୋଇଥିବା ବେଳେ ଏଥିରେ ଇନଷ୍ଟଲ କରାଯାଇଥିବା ଆପ୍ଲିକେସନଗୁଡ଼ିକୁ ଆକ୍ସେସ କରିବା ପାଇଁ <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong>କୁ ରିମୋଟ ଆକ୍ସେସ ପ୍ରଦାନ କରିବାକୁ ଦିଅନ୍ତୁ।"</string>
<string name="summary_app_streaming" product="tablet" msgid="2996373715966272792">"<strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong>କୁ, ଏହି ଟାବଲେଟଟି ସଂଯୁକ୍ତ ହୋଇଥିବା ବେଳେ ଏଥିରେ ଇନଷ୍ଟଲ କରାଯାଇଥିବା ଆପ୍ଲିକେସନଗୁଡ଼ିକୁ ଆକ୍ସେସ କରିବା ପାଇଁ <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong>କୁ ରିମୋଟ ଆକ୍ସେସ ପ୍ରଦାନ କରିବାକୁ ଦିଅନ୍ତୁ।"</string>
<string name="summary_app_streaming" product="device" msgid="7614171699434639963">"<strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong>କୁ, ଏହି ଡିଭାଇସଟି ସଂଯୁକ୍ତ ହୋଇଥିବା ବେଳେ ଏଥିରେ ଇନଷ୍ଟଲ କରାଯାଇଥିବା ଆପ୍ଲିକେସନଗୁଡ଼ିକୁ ଆକ୍ସେସ କରିବା ପାଇଁ <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong>କୁ ରିମୋଟ ଆକ୍ସେସ ପ୍ରଦାନ କରିବାକୁ ଦିଅନ୍ତୁ।"</string>
+ <string name="helper_title_app_streaming" msgid="4151687003439969765">"କ୍ରସ-ଡିଭାଇସ ସେବାଗୁଡ଼ିକ"</string>
+ <string name="helper_summary_app_streaming" msgid="5344341720432827388">"ଆପଣଙ୍କ ଡିଭାଇସଗୁଡ଼ିକ ମଧ୍ୟରେ ଆପ୍ସକୁ ଷ୍ଟ୍ରିମ କରିବା ପାଇଁ ଏହି ସେବାକୁ ବ୍ୟବହାର କରାଯାଏ"</string>
<string name="title_automotive_projection" msgid="3296005598978412847"></string>
<string name="summary_automotive_projection" msgid="8683801274662496164"></string>
<string name="title_computer" msgid="4693714143506569253">"ଆପଣଙ୍କ ଫୋନରୁ ଏହି ସୂଚନାକୁ ଆକ୍ସେସ କରିବା ପାଇଁ <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong>କୁ ଅନୁମତି ଦିଅନ୍ତୁ"</string>
<string name="summary_computer" msgid="3798467601598297062"></string>
+ <string name="permission_notification" msgid="693762568127741203">"ବିଜ୍ଞପ୍ତିଗୁଡ଼ିକ"</string>
+ <string name="permission_notification_summary" msgid="4398672775023193663">"ଯୋଗାଯୋଗ, ମେସେଜ ଏବଂ ଫଟୋଗୁଡ଼ିକ ପରି ସୂଚନା ସମେତ ସମସ୍ତ ବିଜ୍ଞପ୍ତିକୁ ପଢ଼ିପାରିବ"</string>
+ <string name="permission_storage" msgid="6831099350839392343">"ଫଟୋ ଏବଂ ମିଡିଆ"</string>
+ <string name="permission_storage_summary" msgid="3918240895519506417"></string>
+ <string name="helper_title_computer" msgid="4671071173916176037">"Google Play ସେବାଗୁଡ଼ିକ"</string>
+ <string name="helper_summary_computer" product="default" msgid="467996390095403648">"ଏହି ସେବା ଆପଣଙ୍କ ଫୋନରୁ ଅନ୍ୟ ଡିଭାଇସଗୁଡ଼ିକୁ ଫଟୋ, ମିଡିଆ ଏବଂ ବିଜ୍ଞପ୍ତି ସେୟାର କରେ"</string>
+ <string name="helper_summary_computer" product="tablet" msgid="467996390095403648">"ଏହି ସେବା ଆପଣଙ୍କ ଫୋନରୁ ଅନ୍ୟ ଡିଭାଇସଗୁଡ଼ିକୁ ଫଟୋ, ମିଡିଆ ଏବଂ ବିଜ୍ଞପ୍ତି ସେୟାର କରେ"</string>
<string name="profile_name_generic" msgid="6851028682723034988">"ଡିଭାଇସ୍"</string>
<string name="summary_generic" msgid="2346762210105903720"></string>
<string name="consent_yes" msgid="8344487259618762872">"ଅନୁମତି ଦିଅନ୍ତୁ"</string>
<string name="consent_no" msgid="2640796915611404382">"ଅନୁମତି ଦିଅନ୍ତୁ ନାହିଁ"</string>
+ <string name="consent_ok" msgid="3662376764371001106">"ଠିକ୍ ଅଛି"</string>
<string name="permission_sync_confirmation_title" msgid="667074294393493186">"ଆପଣଙ୍କ ୱାଚକୁ ଆପ ଅନୁମତିଗୁଡ଼ିକ ଟ୍ରାନ୍ସଫର କରନ୍ତୁ"</string>
<string name="permission_sync_summary" msgid="8873391306499120778">"ଆପଣଙ୍କ ୱାଚ ସେଟ ଅପ କରିବାକୁ ସହଜ କରିବା ପାଇଁ, ସେଟଅପ ସମୟରେ ଆପଣଙ୍କର ୱାଚରେ ଇନଷ୍ଟଲ କରାଯାଇଥିବା ଆପଗୁଡ଼ିକ ଆପଣଙ୍କ ଫୋନରେ ଥିବା ଆପଗୁଡ଼ିକ ପରି ସମାନ ଅନୁମତିଗୁଡ଼ିକ ବ୍ୟବହାର କରିବ।\n\n ଏହି ଅନୁମତିଗୁଡ଼ିକରେ ଆପଣଙ୍କ ୱାଚର ମାଇକ୍ରୋଫୋନ ଏବଂ ଲୋକେସନକୁ ଆକ୍ସେସ ଅନ୍ତର୍ଭୁକ୍ତ ହୋଇପାରେ।"</string>
</resources>
diff --git a/packages/CompanionDeviceManager/res/values-pa/strings.xml b/packages/CompanionDeviceManager/res/values-pa/strings.xml
index c28be25..93b018e 100644
--- a/packages/CompanionDeviceManager/res/values-pa/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-pa/strings.xml
@@ -22,18 +22,30 @@
<string name="chooser_title" msgid="2262294130493605839">"<strong><xliff:g id="APP_NAME">%2$s</xliff:g></strong> ਵੱਲੋਂ ਪ੍ਰਬੰਧਿਤ ਕੀਤੇ ਜਾਣ ਲਈ <xliff:g id="PROFILE_NAME">%1$s</xliff:g> ਚੁਣੋ"</string>
<string name="summary_watch" product="default" msgid="7113724443198337683">"<xliff:g id="APP_NAME">%1$s</xliff:g> ਨੂੰ ਤੁਹਾਡੀਆਂ ਸੂਚਨਾਵਾਂ ਨਾਲ ਅੰਤਰਕਿਰਿਆ ਕਰਨ ਅਤੇ ਤੁਹਾਡੇ ਫ਼ੋਨ, SMS, ਸੰਪਰਕ ਅਤੇ ਕੈਲੰਡਰ ਦੀਆਂ ਇਜਾਜ਼ਤਾਂ ਤੱਕ ਪਹੁੰਚ ਕਰਨ ਦੀ ਇਜਾਜ਼ਤ ਹੋਵੇਗੀ।"</string>
<string name="summary_watch" product="tablet" msgid="7113724443198337683">"<xliff:g id="APP_NAME">%1$s</xliff:g> ਨੂੰ ਤੁਹਾਡੀਆਂ ਸੂਚਨਾਵਾਂ ਨਾਲ ਅੰਤਰਕਿਰਿਆ ਕਰਨ ਅਤੇ ਤੁਹਾਡੇ ਫ਼ੋਨ, SMS, ਸੰਪਰਕ ਅਤੇ ਕੈਲੰਡਰ ਦੀਆਂ ਇਜਾਜ਼ਤਾਂ ਤੱਕ ਪਹੁੰਚ ਕਰਨ ਦੀ ਇਜਾਜ਼ਤ ਹੋਵੇਗੀ।"</string>
- <string name="title_app_streaming" msgid="4459136600249308574">"ਕੀ <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong&gt ਨੂੰ ਐਪਲੀਕੇਸ਼ਨਾਂ ਸਟ੍ਰੀਮ ਕਰਨ ਦੀ ਆਗਿਆ ਦੇਣੀ ਹੈ?"</string>
+ <string name="permission_apps" msgid="6142133265286656158">"ਐਪਾਂ"</string>
+ <string name="permission_apps_summary" msgid="798718816711515431">"ਆਪਣੇ ਫ਼ੋਨ ਦੀਆਂ ਐਪਾਂ ਨੂੰ ਸਟ੍ਰੀਮ ਕਰੋ"</string>
+ <string name="title_app_streaming" msgid="2270331024626446950">"<strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> ਨੂੰ ਤੁਹਾਡੇ ਫ਼ੋਨ ਤੋਂ ਇਸ ਜਾਣਕਾਰੀ ਤੱਕ ਪਹੁੰਚ ਕਰਨ ਦੀ ਆਗਿਆ ਦਿਓ"</string>
<string name="summary_app_streaming" product="default" msgid="6105916810614498138">"ਕਨੈਕਟ ਹੋਣ \'ਤੇ ਇਸ ਫ਼ੋਨ \'ਤੇ ਸਥਾਪਤ ਐਪਲੀਕੇਸ਼ਨਾਂ ਤੱਕ ਪਹੁੰਚ ਕਰਨ ਲਈ <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> ਨੂੰ <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong> ਨੂੰ ਰਿਮੋਟ ਪਹੁੰਚ ਮੁਹੱਈਆ ਕਰਵਾਉਣ ਦਿਓ।"</string>
<string name="summary_app_streaming" product="tablet" msgid="2996373715966272792">"ਕਨੈਕਟ ਹੋਣ \'ਤੇ ਇਸ ਟੈਬਲੈੱਟ \'ਤੇ ਸਥਾਪਤ ਐਪਲੀਕੇਸ਼ਨਾਂ ਤੱਕ ਪਹੁੰਚ ਕਰਨ ਲਈ <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> ਨੂੰ <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong> ਨੂੰ ਰਿਮੋਟ ਪਹੁੰਚ ਮੁਹੱਈਆ ਕਰਵਾਉਣ ਦਿਓ।"</string>
<string name="summary_app_streaming" product="device" msgid="7614171699434639963">"ਕਨੈਕਟ ਹੋਣ \'ਤੇ ਇਸ ਡੀਵਾਈਸ \'ਤੇ ਸਥਾਪਤ ਐਪਲੀਕੇਸ਼ਨਾਂ ਤੱਕ ਪਹੁੰਚ ਕਰਨ ਲਈ <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> ਨੂੰ <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong> ਨੂੰ ਰਿਮੋਟ ਪਹੁੰਚ ਮੁਹੱਈਆ ਕਰਵਾਉਣ ਦਿਓ।"</string>
+ <string name="helper_title_app_streaming" msgid="4151687003439969765">"ਕ੍ਰਾਸ-ਡੀਵਾਈਸ ਸੇਵਾਵਾਂ"</string>
+ <string name="helper_summary_app_streaming" msgid="5344341720432827388">"ਇਸ ਸੇਵਾ ਦੀ ਵਰਤੋਂ ਤੁਹਾਡੇ ਡੀਵਾਈਸਾਂ ਵਿਚਕਾਰ ਐਪਾਂ ਨੂੰ ਸਟ੍ਰੀਮ ਕਰਨ ਲਈ ਕੀਤੀ ਜਾਂਦੀ ਹੈ"</string>
<string name="title_automotive_projection" msgid="3296005598978412847"></string>
<string name="summary_automotive_projection" msgid="8683801274662496164"></string>
<string name="title_computer" msgid="4693714143506569253">"<strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> ਨੂੰ ਤੁਹਾਡੇ ਫ਼ੋਨ ਤੋਂ ਇਸ ਜਾਣਕਾਰੀ ਤੱਕ ਪਹੁੰਚ ਕਰਨ ਦੀ ਆਗਿਆ ਦਿਓ"</string>
<string name="summary_computer" msgid="3798467601598297062"></string>
+ <string name="permission_notification" msgid="693762568127741203">"ਸੂਚਨਾਵਾਂ"</string>
+ <string name="permission_notification_summary" msgid="4398672775023193663">"ਤੁਸੀਂ ਸਾਰੀਆਂ ਸੂਚਨਾਵਾਂ ਪੜ੍ਹ ਸਕਦੇ ਹੋ, ਜਿਨ੍ਹਾਂ ਵਿੱਚ ਸੰਪਰਕਾਂ, ਸੁਨੇਹਿਆਂ ਅਤੇ ਫ਼ੋਟੋਆਂ ਵਰਗੀ ਜਾਣਕਾਰੀ ਸ਼ਾਮਲ ਹੁੰਦੀ ਹੈ"</string>
+ <string name="permission_storage" msgid="6831099350839392343">"ਫ਼ੋਟੋਆਂ ਅਤੇ ਮੀਡੀਆ"</string>
+ <string name="permission_storage_summary" msgid="3918240895519506417"></string>
+ <string name="helper_title_computer" msgid="4671071173916176037">"Google Play ਸੇਵਾਵਾਂ"</string>
+ <string name="helper_summary_computer" product="default" msgid="467996390095403648">"ਇਹ ਸੇਵਾ ਫ਼ੋਟੋਆਂ, ਮੀਡੀਆ ਅਤੇ ਸੂਚਨਾਵਾਂ ਨੂੰ ਤੁਹਾਡੇ ਫ਼ੋਨ ਤੋਂ ਹੋਰ ਡੀਵਾਈਸਾਂ \'ਤੇ ਸਾਂਝਾ ਕਰਦੀ ਹੈ"</string>
+ <string name="helper_summary_computer" product="tablet" msgid="467996390095403648">"ਇਹ ਸੇਵਾ ਫ਼ੋਟੋਆਂ, ਮੀਡੀਆ ਅਤੇ ਸੂਚਨਾਵਾਂ ਨੂੰ ਤੁਹਾਡੇ ਫ਼ੋਨ ਤੋਂ ਹੋਰ ਡੀਵਾਈਸਾਂ \'ਤੇ ਸਾਂਝਾ ਕਰਦੀ ਹੈ"</string>
<string name="profile_name_generic" msgid="6851028682723034988">"ਡੀਵਾਈਸ"</string>
<string name="summary_generic" msgid="2346762210105903720"></string>
<string name="consent_yes" msgid="8344487259618762872">"ਇਜਾਜ਼ਤ ਦਿਓ"</string>
<string name="consent_no" msgid="2640796915611404382">"ਇਜਾਜ਼ਤ ਨਾ ਦਿਓ"</string>
+ <string name="consent_ok" msgid="3662376764371001106">"ਠੀਕ ਹੈ"</string>
<string name="permission_sync_confirmation_title" msgid="667074294393493186">"ਐਪ ਇਜਾਜ਼ਤਾਂ ਨੂੰ ਆਪਣੀ ਘੜੀ \'ਤੇ ਟ੍ਰਾਂਸਫ਼ਰ ਕਰੋ"</string>
<string name="permission_sync_summary" msgid="8873391306499120778">"ਤੁਹਾਡੀ ਘੜੀ ਦਾ ਸੈੱਟਅੱਪ ਕਰਨਾ ਆਸਾਨ ਬਣਾਉਣ ਲਈ, ਤੁਹਾਡੀ ਘੜੀ \'ਤੇ ਸਥਾਪਤ ਐਪਾਂ ਸੈੱਟਅੱਪ ਦੌਰਾਨ ਉਹੀ ਇਜਾਜ਼ਤਾਂ ਵਰਤਣਗੀਆਂ ਜੋ ਤੁਹਾਡਾ ਫ਼ੋਨ ਵਰਤਦਾ ਹੈ।\n\n ਇਨ੍ਹਾਂ ਇਜਾਜ਼ਤਾਂ ਵਿੱਚ ਤੁਹਾਡੀ ਘੜੀ ਦੇ ਮਾਈਕ੍ਰੋਫ਼ੋਨ ਅਤੇ ਟਿਕਾਣੇ ਤੱਕ ਪਹੁੰਚ ਸ਼ਾਮਲ ਹੋ ਸਕਦੀ ਹੈ।"</string>
</resources>
diff --git a/packages/CompanionDeviceManager/res/values-pl/strings.xml b/packages/CompanionDeviceManager/res/values-pl/strings.xml
index f9fd206..a15af4b 100644
--- a/packages/CompanionDeviceManager/res/values-pl/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-pl/strings.xml
@@ -22,18 +22,30 @@
<string name="chooser_title" msgid="2262294130493605839">"Wybierz profil <xliff:g id="PROFILE_NAME">%1$s</xliff:g>, którym ma zarządzać aplikacja <strong><xliff:g id="APP_NAME">%2$s</xliff:g></strong>"</string>
<string name="summary_watch" product="default" msgid="7113724443198337683">"Aplikacja <xliff:g id="APP_NAME">%1$s</xliff:g> będzie mogła korzystać z powiadomień oraz uprawnień dotyczących Telefonu, SMS-ów, Kontaktów i Kalendarza."</string>
<string name="summary_watch" product="tablet" msgid="7113724443198337683">"Aplikacja <xliff:g id="APP_NAME">%1$s</xliff:g> będzie mogła korzystać z powiadomień oraz uprawnień dotyczących Telefonu, SMS-ów, Kontaktów i Kalendarza."</string>
- <string name="title_app_streaming" msgid="4459136600249308574">"Zezwolić aplikacji <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> na strumieniowanie danych z aplikacji?"</string>
+ <string name="permission_apps" msgid="6142133265286656158">"Aplikacje"</string>
+ <string name="permission_apps_summary" msgid="798718816711515431">"Odtwarzaj strumieniowo aplikacje z telefonu"</string>
+ <string name="title_app_streaming" msgid="2270331024626446950">"Zezwól aplikacji <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> na dostęp do tych informacji na Twoim telefonie"</string>
<string name="summary_app_streaming" product="default" msgid="6105916810614498138">"Zezwól na zapewnianie przez aplikację <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> zdalnego dostępu do aplikacji zainstalowanych na telefonie <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong> po połączeniu jej z tym telefonem."</string>
<string name="summary_app_streaming" product="tablet" msgid="2996373715966272792">"Zezwól na zapewnianie przez aplikację <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> zdalnego dostępu do aplikacji zainstalowanych na tablecie <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong> po połączeniu jej z tym tabletem."</string>
<string name="summary_app_streaming" product="device" msgid="7614171699434639963">"Zezwól na zapewnianie przez aplikację <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> zdalnego dostępu do aplikacji zainstalowanych na urządzeniu <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong> po połączeniu jej z urządzeniem."</string>
+ <string name="helper_title_app_streaming" msgid="4151687003439969765">"Usługi na innym urządzeniu"</string>
+ <string name="helper_summary_app_streaming" msgid="5344341720432827388">"Ta usługa jest używana do strumieniowego odtwarzania danych z aplikacji między urządzeniami"</string>
<string name="title_automotive_projection" msgid="3296005598978412847"></string>
<string name="summary_automotive_projection" msgid="8683801274662496164"></string>
<string name="title_computer" msgid="4693714143506569253">"Zezwól aplikacji <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> na dostęp do tych informacji na Twoim telefonie"</string>
<string name="summary_computer" msgid="3798467601598297062"></string>
+ <string name="permission_notification" msgid="693762568127741203">"Powiadomienia"</string>
+ <string name="permission_notification_summary" msgid="4398672775023193663">"Może odczytywać wszystkie powiadomienia, w tym informacje takie jak kontakty, wiadomości i zdjęcia"</string>
+ <string name="permission_storage" msgid="6831099350839392343">"Zdjęcia i multimedia"</string>
+ <string name="permission_storage_summary" msgid="3918240895519506417"></string>
+ <string name="helper_title_computer" msgid="4671071173916176037">"Usługi Google Play"</string>
+ <string name="helper_summary_computer" product="default" msgid="467996390095403648">"Ta usługa udostępnia zdjęcia, multimedia i powiadomienia z telefonu innym urządzeniom"</string>
+ <string name="helper_summary_computer" product="tablet" msgid="467996390095403648">"Ta usługa udostępnia zdjęcia, multimedia i powiadomienia z telefonu innym urządzeniom"</string>
<string name="profile_name_generic" msgid="6851028682723034988">"urządzenie"</string>
<string name="summary_generic" msgid="2346762210105903720"></string>
<string name="consent_yes" msgid="8344487259618762872">"Zezwól"</string>
<string name="consent_no" msgid="2640796915611404382">"Nie zezwalaj"</string>
+ <string name="consent_ok" msgid="3662376764371001106">"OK"</string>
<string name="permission_sync_confirmation_title" msgid="667074294393493186">"Przenieś uprawnienia aplikacji na zegarek"</string>
<string name="permission_sync_summary" msgid="8873391306499120778">"Aby łatwiej było skonfigurować zegarek, aplikacje zainstalowane na nim podczas konfiguracji będą korzystały z tych samych uprawnień co telefon.\n\n Może to oznaczać dostęp do mikrofonu i lokalizacji na zegarku."</string>
</resources>
diff --git a/packages/CompanionDeviceManager/res/values-pt-rBR/strings.xml b/packages/CompanionDeviceManager/res/values-pt-rBR/strings.xml
index 161188c..7d22823 100644
--- a/packages/CompanionDeviceManager/res/values-pt-rBR/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-pt-rBR/strings.xml
@@ -22,18 +22,30 @@
<string name="chooser_title" msgid="2262294130493605839">"Escolha um <xliff:g id="PROFILE_NAME">%1$s</xliff:g> para ser gerenciado pelo app <strong><xliff:g id="APP_NAME">%2$s</xliff:g></strong>"</string>
<string name="summary_watch" product="default" msgid="7113724443198337683">"O app <xliff:g id="APP_NAME">%1$s</xliff:g> poderá interagir com suas notificações e acessar as permissões do Telefone, de SMS, de Contatos e da Agenda."</string>
<string name="summary_watch" product="tablet" msgid="7113724443198337683">"O app <xliff:g id="APP_NAME">%1$s</xliff:g> poderá interagir com suas notificações e acessar as permissões do Telefone, de SMS, de Contatos e da Agenda."</string>
- <string name="title_app_streaming" msgid="4459136600249308574">"Permitir que o app <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> faça streaming de aplicativos?"</string>
+ <string name="permission_apps" msgid="6142133265286656158">"Apps"</string>
+ <string name="permission_apps_summary" msgid="798718816711515431">"Faça streaming dos apps do seu smartphone"</string>
+ <string name="title_app_streaming" msgid="2270331024626446950">"Permitir que o app <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> acesse essas informações do smartphone"</string>
<string name="summary_app_streaming" product="default" msgid="6105916810614498138">"Permita que o app <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> conceda ao <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong> acesso remoto aos aplicativos instalados no smartphone quando ele estiver conectado."</string>
<string name="summary_app_streaming" product="tablet" msgid="2996373715966272792">"Permita que o app <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> conceda ao <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong> acesso remoto aos aplicativos instalados no tablet quando ele estiver conectado."</string>
<string name="summary_app_streaming" product="device" msgid="7614171699434639963">"Permita que o app <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> conceda ao <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong> acesso remoto aos aplicativos instalados no dispositivo quando ele estiver conectado."</string>
+ <string name="helper_title_app_streaming" msgid="4151687003439969765">"Serviços entre dispositivos"</string>
+ <string name="helper_summary_app_streaming" msgid="5344341720432827388">"Este serviço é usado para fazer streaming de apps entre seus dispositivos"</string>
<string name="title_automotive_projection" msgid="3296005598978412847"></string>
<string name="summary_automotive_projection" msgid="8683801274662496164"></string>
<string name="title_computer" msgid="4693714143506569253">"Autorizar que <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> acesse essas informações do smartphone"</string>
<string name="summary_computer" msgid="3798467601598297062"></string>
+ <string name="permission_notification" msgid="693762568127741203">"Notificações"</string>
+ <string name="permission_notification_summary" msgid="4398672775023193663">"Pode ler todas as notificações, incluindo informações como contatos, mensagens e fotos"</string>
+ <string name="permission_storage" msgid="6831099350839392343">"Fotos e mídia"</string>
+ <string name="permission_storage_summary" msgid="3918240895519506417"></string>
+ <string name="helper_title_computer" msgid="4671071173916176037">"Google Play Services"</string>
+ <string name="helper_summary_computer" product="default" msgid="467996390095403648">"Este serviço compartilha fotos, mídia e notificações do seu smartphone para outros dispositivos"</string>
+ <string name="helper_summary_computer" product="tablet" msgid="467996390095403648">"Este serviço compartilha fotos, mídia e notificações do seu smartphone para outros dispositivos"</string>
<string name="profile_name_generic" msgid="6851028682723034988">"dispositivo"</string>
<string name="summary_generic" msgid="2346762210105903720"></string>
<string name="consent_yes" msgid="8344487259618762872">"Permitir"</string>
<string name="consent_no" msgid="2640796915611404382">"Não permitir"</string>
+ <string name="consent_ok" msgid="3662376764371001106">"OK"</string>
<string name="permission_sync_confirmation_title" msgid="667074294393493186">"Transferir as permissões de apps para o relógio"</string>
<string name="permission_sync_summary" msgid="8873391306499120778">"Para facilitar a configuração do relógio, os apps instalados nele durante a configuração vão usar as mesmas permissões que o smartphone.\n\n Essas permissões podem incluir acesso ao microfone ou à localização do relógio."</string>
</resources>
diff --git a/packages/CompanionDeviceManager/res/values-pt-rPT/strings.xml b/packages/CompanionDeviceManager/res/values-pt-rPT/strings.xml
index 9124a40..e0c717c 100644
--- a/packages/CompanionDeviceManager/res/values-pt-rPT/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-pt-rPT/strings.xml
@@ -22,18 +22,30 @@
<string name="chooser_title" msgid="2262294130493605839">"Escolha um <xliff:g id="PROFILE_NAME">%1$s</xliff:g> para ser gerido pela app <strong><xliff:g id="APP_NAME">%2$s</xliff:g></strong>"</string>
<string name="summary_watch" product="default" msgid="7113724443198337683">"A app <xliff:g id="APP_NAME">%1$s</xliff:g> poderá interagir com as suas notificações e aceder às autorizações do Telefone, SMS, Contactos e Calendário."</string>
<string name="summary_watch" product="tablet" msgid="7113724443198337683">"A app <xliff:g id="APP_NAME">%1$s</xliff:g> poderá interagir com as suas notificações e aceder às autorizações do Telefone, SMS, Contactos e Calendário."</string>
- <string name="title_app_streaming" msgid="4459136600249308574">"Permitir que a app <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> faça stream de aplicações?"</string>
+ <string name="permission_apps" msgid="6142133265286656158">"Apps"</string>
+ <string name="permission_apps_summary" msgid="798718816711515431">"Faça stream das apps do telemóvel"</string>
+ <string name="title_app_streaming" msgid="2270331024626446950">"Permita que a app <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> aceda a estas informações do seu telemóvel"</string>
<string name="summary_app_streaming" product="default" msgid="6105916810614498138">"Permita que a app <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> forneça acesso remoto ao <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong> para aceder a aplicações instaladas neste telemóvel quando estiver ligado."</string>
<string name="summary_app_streaming" product="tablet" msgid="2996373715966272792">"Permita que a app <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> forneça acesso remoto ao <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong> para aceder a aplicações instaladas neste tablet quando estiver ligado."</string>
<string name="summary_app_streaming" product="device" msgid="7614171699434639963">"Permita que a app <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> forneça acesso remoto ao <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong> para aceder a aplicações instaladas neste dispositivo quando estiver ligado."</string>
+ <string name="helper_title_app_streaming" msgid="4151687003439969765">"Serviços entre dispositivos"</string>
+ <string name="helper_summary_app_streaming" msgid="5344341720432827388">"Este serviço é utilizado para fazer stream de apps entre os seus dispositivos"</string>
<string name="title_automotive_projection" msgid="3296005598978412847"></string>
<string name="summary_automotive_projection" msgid="8683801274662496164"></string>
<string name="title_computer" msgid="4693714143506569253">"Permita que a app <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> aceda a estas informações do seu telemóvel"</string>
<string name="summary_computer" msgid="3798467601598297062"></string>
+ <string name="permission_notification" msgid="693762568127741203">"Notificações"</string>
+ <string name="permission_notification_summary" msgid="4398672775023193663">"Pode ler todas as notificações, incluindo informações como contratos, mensagens e fotos"</string>
+ <string name="permission_storage" msgid="6831099350839392343">"Fotos e multimédia"</string>
+ <string name="permission_storage_summary" msgid="3918240895519506417"></string>
+ <string name="helper_title_computer" msgid="4671071173916176037">"Serviços do Google Play"</string>
+ <string name="helper_summary_computer" product="default" msgid="467996390095403648">"Este serviço partilha fotos, conteúdo multimédia e notificações do seu telemóvel para outros dispositivos"</string>
+ <string name="helper_summary_computer" product="tablet" msgid="467996390095403648">"Este serviço partilha fotos, conteúdo multimédia e notificações do seu telemóvel para outros dispositivos"</string>
<string name="profile_name_generic" msgid="6851028682723034988">"dispositivo"</string>
<string name="summary_generic" msgid="2346762210105903720"></string>
<string name="consent_yes" msgid="8344487259618762872">"Permitir"</string>
<string name="consent_no" msgid="2640796915611404382">"Não permitir"</string>
+ <string name="consent_ok" msgid="3662376764371001106">"OK"</string>
<string name="permission_sync_confirmation_title" msgid="667074294393493186">"Transfira as autorizações da app para o seu relógio"</string>
<string name="permission_sync_summary" msgid="8873391306499120778">"Para facilitar a configuração do seu relógio, as apps instaladas no mesmo durante a configuração utilizarão as mesmas autorizações que o telemóvel.\n\n Estas autorizações podem incluir o acesso ao microfone e à localização do seu relógio."</string>
</resources>
diff --git a/packages/CompanionDeviceManager/res/values-pt/strings.xml b/packages/CompanionDeviceManager/res/values-pt/strings.xml
index 161188c..7d22823 100644
--- a/packages/CompanionDeviceManager/res/values-pt/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-pt/strings.xml
@@ -22,18 +22,30 @@
<string name="chooser_title" msgid="2262294130493605839">"Escolha um <xliff:g id="PROFILE_NAME">%1$s</xliff:g> para ser gerenciado pelo app <strong><xliff:g id="APP_NAME">%2$s</xliff:g></strong>"</string>
<string name="summary_watch" product="default" msgid="7113724443198337683">"O app <xliff:g id="APP_NAME">%1$s</xliff:g> poderá interagir com suas notificações e acessar as permissões do Telefone, de SMS, de Contatos e da Agenda."</string>
<string name="summary_watch" product="tablet" msgid="7113724443198337683">"O app <xliff:g id="APP_NAME">%1$s</xliff:g> poderá interagir com suas notificações e acessar as permissões do Telefone, de SMS, de Contatos e da Agenda."</string>
- <string name="title_app_streaming" msgid="4459136600249308574">"Permitir que o app <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> faça streaming de aplicativos?"</string>
+ <string name="permission_apps" msgid="6142133265286656158">"Apps"</string>
+ <string name="permission_apps_summary" msgid="798718816711515431">"Faça streaming dos apps do seu smartphone"</string>
+ <string name="title_app_streaming" msgid="2270331024626446950">"Permitir que o app <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> acesse essas informações do smartphone"</string>
<string name="summary_app_streaming" product="default" msgid="6105916810614498138">"Permita que o app <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> conceda ao <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong> acesso remoto aos aplicativos instalados no smartphone quando ele estiver conectado."</string>
<string name="summary_app_streaming" product="tablet" msgid="2996373715966272792">"Permita que o app <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> conceda ao <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong> acesso remoto aos aplicativos instalados no tablet quando ele estiver conectado."</string>
<string name="summary_app_streaming" product="device" msgid="7614171699434639963">"Permita que o app <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> conceda ao <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong> acesso remoto aos aplicativos instalados no dispositivo quando ele estiver conectado."</string>
+ <string name="helper_title_app_streaming" msgid="4151687003439969765">"Serviços entre dispositivos"</string>
+ <string name="helper_summary_app_streaming" msgid="5344341720432827388">"Este serviço é usado para fazer streaming de apps entre seus dispositivos"</string>
<string name="title_automotive_projection" msgid="3296005598978412847"></string>
<string name="summary_automotive_projection" msgid="8683801274662496164"></string>
<string name="title_computer" msgid="4693714143506569253">"Autorizar que <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> acesse essas informações do smartphone"</string>
<string name="summary_computer" msgid="3798467601598297062"></string>
+ <string name="permission_notification" msgid="693762568127741203">"Notificações"</string>
+ <string name="permission_notification_summary" msgid="4398672775023193663">"Pode ler todas as notificações, incluindo informações como contatos, mensagens e fotos"</string>
+ <string name="permission_storage" msgid="6831099350839392343">"Fotos e mídia"</string>
+ <string name="permission_storage_summary" msgid="3918240895519506417"></string>
+ <string name="helper_title_computer" msgid="4671071173916176037">"Google Play Services"</string>
+ <string name="helper_summary_computer" product="default" msgid="467996390095403648">"Este serviço compartilha fotos, mídia e notificações do seu smartphone para outros dispositivos"</string>
+ <string name="helper_summary_computer" product="tablet" msgid="467996390095403648">"Este serviço compartilha fotos, mídia e notificações do seu smartphone para outros dispositivos"</string>
<string name="profile_name_generic" msgid="6851028682723034988">"dispositivo"</string>
<string name="summary_generic" msgid="2346762210105903720"></string>
<string name="consent_yes" msgid="8344487259618762872">"Permitir"</string>
<string name="consent_no" msgid="2640796915611404382">"Não permitir"</string>
+ <string name="consent_ok" msgid="3662376764371001106">"OK"</string>
<string name="permission_sync_confirmation_title" msgid="667074294393493186">"Transferir as permissões de apps para o relógio"</string>
<string name="permission_sync_summary" msgid="8873391306499120778">"Para facilitar a configuração do relógio, os apps instalados nele durante a configuração vão usar as mesmas permissões que o smartphone.\n\n Essas permissões podem incluir acesso ao microfone ou à localização do relógio."</string>
</resources>
diff --git a/packages/CompanionDeviceManager/res/values-ro/strings.xml b/packages/CompanionDeviceManager/res/values-ro/strings.xml
index da7ae9e..61b47fb 100644
--- a/packages/CompanionDeviceManager/res/values-ro/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-ro/strings.xml
@@ -22,18 +22,30 @@
<string name="chooser_title" msgid="2262294130493605839">"Alegeți un profil <xliff:g id="PROFILE_NAME">%1$s</xliff:g> pe care să îl gestioneze <strong><xliff:g id="APP_NAME">%2$s</xliff:g></strong>"</string>
<string name="summary_watch" product="default" msgid="7113724443198337683">"<xliff:g id="APP_NAME">%1$s</xliff:g> va putea să interacționeze cu notificările dvs. și să vă acceseze permisiunile pentru Telefon, SMS-uri, Agendă și Calendar."</string>
<string name="summary_watch" product="tablet" msgid="7113724443198337683">"<xliff:g id="APP_NAME">%1$s</xliff:g> va putea să interacționeze cu notificările dvs. și să vă acceseze permisiunile pentru Telefon, SMS-uri, Agendă și Calendar."</string>
- <string name="title_app_streaming" msgid="4459136600249308574">"Lăsați <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> să redea în stream aplicații?"</string>
+ <string name="permission_apps" msgid="6142133265286656158">"Aplicații"</string>
+ <string name="permission_apps_summary" msgid="798718816711515431">"Să redea în stream aplicațiile telefonului"</string>
+ <string name="title_app_streaming" msgid="2270331024626446950">"Permiteți ca <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> să acceseze aceste informații de pe telefon"</string>
<string name="summary_app_streaming" product="default" msgid="6105916810614498138">"Lăsați <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> să ofere acces la distanță pentru <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong> ca să se poată accesa aplicațiile instalate pe acest telefon când se conectează utilizatorul."</string>
<string name="summary_app_streaming" product="tablet" msgid="2996373715966272792">"Lăsați <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> să ofere acces la distanță pentru <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong> ca să se poată accesa aplicațiile instalate pe această tabletă când se conectează utilizatorul."</string>
<string name="summary_app_streaming" product="device" msgid="7614171699434639963">"Lăsați <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> să ofere acces la distanță pentru <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong> ca să se poată accesa aplicațiile instalate pe acest dispozitiv când se conectează utilizatorul."</string>
+ <string name="helper_title_app_streaming" msgid="4151687003439969765">"Servicii pe mai multe dispozitive"</string>
+ <string name="helper_summary_app_streaming" msgid="5344341720432827388">"Acest serviciu se folosește pentru a proiecta aplicații între dispozitive"</string>
<string name="title_automotive_projection" msgid="3296005598978412847"></string>
<string name="summary_automotive_projection" msgid="8683801274662496164"></string>
<string name="title_computer" msgid="4693714143506569253">"Permiteți ca <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> să acceseze aceste informații de pe telefon"</string>
<string name="summary_computer" msgid="3798467601598297062"></string>
+ <string name="permission_notification" msgid="693762568127741203">"Notificări"</string>
+ <string name="permission_notification_summary" msgid="4398672775023193663">"Poate să citească toate notificările, inclusiv informații cum ar fi contracte, mesaje și fotografii"</string>
+ <string name="permission_storage" msgid="6831099350839392343">"Fotografii și media"</string>
+ <string name="permission_storage_summary" msgid="3918240895519506417"></string>
+ <string name="helper_title_computer" msgid="4671071173916176037">"Servicii Google Play"</string>
+ <string name="helper_summary_computer" product="default" msgid="467996390095403648">"Serviciul trimite fotografii, conținut media și notificări de pe telefon pe alte dispozitive"</string>
+ <string name="helper_summary_computer" product="tablet" msgid="467996390095403648">"Serviciul trimite fotografii, conținut media și notificări de pe telefon pe alte dispozitive"</string>
<string name="profile_name_generic" msgid="6851028682723034988">"dispozitiv"</string>
<string name="summary_generic" msgid="2346762210105903720"></string>
<string name="consent_yes" msgid="8344487259618762872">"Permiteți"</string>
<string name="consent_no" msgid="2640796915611404382">"Nu permiteți"</string>
+ <string name="consent_ok" msgid="3662376764371001106">"OK"</string>
<string name="permission_sync_confirmation_title" msgid="667074294393493186">"Transferați permisiunile pentru aplicații pe ceas"</string>
<string name="permission_sync_summary" msgid="8873391306499120778">"Ca să configurați mai ușor ceasul, aplicațiile instalate pe ceas în timpul procesului de configurare vor folosi aceleași permisiuni ca telefonul.\n\n Între acestea se poate număra accesul la microfonul și locația ceasului."</string>
</resources>
diff --git a/packages/CompanionDeviceManager/res/values-ru/strings.xml b/packages/CompanionDeviceManager/res/values-ru/strings.xml
index dbb09c9..062314f 100644
--- a/packages/CompanionDeviceManager/res/values-ru/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-ru/strings.xml
@@ -22,18 +22,30 @@
<string name="chooser_title" msgid="2262294130493605839">"Выберите устройство (<xliff:g id="PROFILE_NAME">%1$s</xliff:g>), которым будет управлять приложение <strong><xliff:g id="APP_NAME">%2$s</xliff:g></strong>"</string>
<string name="summary_watch" product="default" msgid="7113724443198337683">"Приложению \"<xliff:g id="APP_NAME">%1$s</xliff:g>\" будет предоставлен доступ к уведомлениям, а также следующие разрешения: телефон, SMS, контакты и календарь."</string>
<string name="summary_watch" product="tablet" msgid="7113724443198337683">"Приложению \"<xliff:g id="APP_NAME">%1$s</xliff:g>\" будет предоставлен доступ к уведомлениям, а также следующие разрешения: телефон, SMS, контакты и календарь."</string>
- <string name="title_app_streaming" msgid="4459136600249308574">"Разрешить приложению <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> транслировать приложения?"</string>
+ <string name="permission_apps" msgid="6142133265286656158">"Приложения"</string>
+ <string name="permission_apps_summary" msgid="798718816711515431">"Трансляция приложений с телефона."</string>
+ <string name="title_app_streaming" msgid="2270331024626446950">"Разрешите приложению <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> получать эту информацию с вашего телефона"</string>
<string name="summary_app_streaming" product="default" msgid="6105916810614498138">"Разрешить приложению <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> при наличии подключения предоставить устройству <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong> удаленный доступ к приложениям, установленным на этом телефоне."</string>
<string name="summary_app_streaming" product="tablet" msgid="2996373715966272792">"Разрешить приложению <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> при наличии подключения предоставить устройству <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong> удаленный доступ к приложениям, установленным на этом планшете."</string>
<string name="summary_app_streaming" product="device" msgid="7614171699434639963">"Разрешить приложению <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> при наличии подключения предоставить устройству <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong> удаленный доступ к приложениям, установленным на этом устройстве."</string>
+ <string name="helper_title_app_streaming" msgid="4151687003439969765">"Сервисы стриминга приложений"</string>
+ <string name="helper_summary_app_streaming" msgid="5344341720432827388">"Этот сервис используется для трансляции приложений с одного устройства на другое."</string>
<string name="title_automotive_projection" msgid="3296005598978412847"></string>
<string name="summary_automotive_projection" msgid="8683801274662496164"></string>
<string name="title_computer" msgid="4693714143506569253">"Разрешите приложению <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> получать эту информацию с вашего телефона"</string>
<string name="summary_computer" msgid="3798467601598297062"></string>
+ <string name="permission_notification" msgid="693762568127741203">"Уведомления"</string>
+ <string name="permission_notification_summary" msgid="4398672775023193663">"Чтение всех уведомлений, в том числе сведений о контактах, сообщениях и фотографиях."</string>
+ <string name="permission_storage" msgid="6831099350839392343">"Фотографии и медиафайлы"</string>
+ <string name="permission_storage_summary" msgid="3918240895519506417"></string>
+ <string name="helper_title_computer" msgid="4671071173916176037">"Сервисы Google Play"</string>
+ <string name="helper_summary_computer" product="default" msgid="467996390095403648">"Этот сервис используется для отправки фотографий, медиафайлов и уведомлений с вашего телефона на другие устройства."</string>
+ <string name="helper_summary_computer" product="tablet" msgid="467996390095403648">"Этот сервис используется для отправки фотографий, медиафайлов и уведомлений с вашего телефона на другие устройства."</string>
<string name="profile_name_generic" msgid="6851028682723034988">"устройство"</string>
<string name="summary_generic" msgid="2346762210105903720"></string>
<string name="consent_yes" msgid="8344487259618762872">"Разрешить"</string>
<string name="consent_no" msgid="2640796915611404382">"Запретить"</string>
+ <string name="consent_ok" msgid="3662376764371001106">"ОК"</string>
<string name="permission_sync_confirmation_title" msgid="667074294393493186">"Перенос разрешений для приложений на часы"</string>
<string name="permission_sync_summary" msgid="8873391306499120778">"Для приложений, установленных на часы во время настройки, будут использоваться те же разрешения, что и на телефоне.\n\n Например, может быть включен доступ к микрофону на часах или сведениям о местоположении."</string>
</resources>
diff --git a/packages/CompanionDeviceManager/res/values-si/strings.xml b/packages/CompanionDeviceManager/res/values-si/strings.xml
index a3de2a3..65f7865 100644
--- a/packages/CompanionDeviceManager/res/values-si/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-si/strings.xml
@@ -22,18 +22,30 @@
<string name="chooser_title" msgid="2262294130493605839">"<strong><xliff:g id="APP_NAME">%2$s</xliff:g></strong> මගින් කළමනාකරණය කරනු ලැබීමට <xliff:g id="PROFILE_NAME">%1$s</xliff:g>ක් තෝරන්න"</string>
<string name="summary_watch" product="default" msgid="7113724443198337683">"<xliff:g id="APP_NAME">%1$s</xliff:g> ඔබගේ දැනුම්දීම් සමඟ අන්තර්ක්රියා කිරීමට සහ ඔබගේ දුරකථනය, කෙටි පණිවුඩ, සම්බන්ධතා සහ දින දර්ශන අවසර වෙත ප්රවේශ වීමට ඉඩ දෙනු ඇත."</string>
<string name="summary_watch" product="tablet" msgid="7113724443198337683">"<xliff:g id="APP_NAME">%1$s</xliff:g> ඔබගේ දැනුම්දීම් සමඟ අන්තර්ක්රියා කිරීමට සහ ඔබගේ දුරකථනය, කෙටි පණිවුඩ, සම්බන්ධතා සහ දින දර්ශන අවසර වෙත ප්රවේශ වීමට ඉඩ දෙනු ඇත."</string>
- <string name="title_app_streaming" msgid="4459136600249308574">"<strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> හට යෙදුම් ප්රවාහ කිරීමට ඉඩ දෙන්නද?"</string>
+ <string name="permission_apps" msgid="6142133265286656158">"යෙදුම්"</string>
+ <string name="permission_apps_summary" msgid="798718816711515431">"ඔබගේ දුරකථනයේ යෙදුම් ප්රවාහ කරන්න"</string>
+ <string name="title_app_streaming" msgid="2270331024626446950">"<strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> හට ඔබගේ දුරකථනයෙන් මෙම තොරතුරුවලට ප්රවේශ වීමට ඉඩ දෙන්න"</string>
<string name="summary_app_streaming" product="default" msgid="6105916810614498138">"සම්බන්ධ වූ විට මෙම දුරකථනයේ ස්ථාපනය කර ඇති යෙදුම් වෙත ප්රවේශ වීමට <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> හට <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong> හට දුරස්ථ ප්රවේශය ලබා දීමට ඉඩ දෙන්න."</string>
<string name="summary_app_streaming" product="tablet" msgid="2996373715966272792">"සම්බන්ධ වූ විට මෙම ටැබ්ලටයේ ස්ථාපනය කර ඇති යෙදුම් වෙත ප්රවේශ වීමට <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> හට <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong> හට දුරස්ථ ප්රවේශය ලබා දීමට ඉඩ දෙන්න."</string>
<string name="summary_app_streaming" product="device" msgid="7614171699434639963">"සම්බන්ධ වූ විට මෙම උපාංගයේ ස්ථාපනය කර ඇති යෙදුම් වෙත ප්රවේශ වීමට <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> හට <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong> හට දුරස්ථ ප්රවේශය ලබා දීමට ඉඩ දෙන්න."</string>
+ <string name="helper_title_app_streaming" msgid="4151687003439969765">"හරස්-උපාංග සේවා"</string>
+ <string name="helper_summary_app_streaming" msgid="5344341720432827388">"මෙම සේවාව ඔබගේ උපාංග අතර යෙදුම් ප්රවාහ කිරීමට භාවිත වේ"</string>
<string name="title_automotive_projection" msgid="3296005598978412847"></string>
<string name="summary_automotive_projection" msgid="8683801274662496164"></string>
<string name="title_computer" msgid="4693714143506569253">"<strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> හට ඔබගේ දුරකථනයෙන් මෙම තොරතුරුවලට ප්රවේශ වීමට ඉඩ දෙන්න"</string>
<string name="summary_computer" msgid="3798467601598297062"></string>
+ <string name="permission_notification" msgid="693762568127741203">"දැනුම්දීම්"</string>
+ <string name="permission_notification_summary" msgid="4398672775023193663">"ගිවිසුම්, පණිවිඩ සහ ඡායාරූප වැනි තොරතුරු ඇතුළුව සියලු දැනුම්දීම් කියවිය හැකිය"</string>
+ <string name="permission_storage" msgid="6831099350839392343">"ඡායාරූප සහ මාධ්ය"</string>
+ <string name="permission_storage_summary" msgid="3918240895519506417"></string>
+ <string name="helper_title_computer" msgid="4671071173916176037">"Google Play සේවා"</string>
+ <string name="helper_summary_computer" product="default" msgid="467996390095403648">"මෙම සේවාව ඔබගේ දුරකථනයෙන් වෙනත් උපාංග වෙත ඡායාරූප, මාධ්ය සහ දැනුම්දීම් බෙදා ගනී"</string>
+ <string name="helper_summary_computer" product="tablet" msgid="467996390095403648">"මෙම සේවාව ඔබගේ දුරකථනයෙන් වෙනත් උපාංග වෙත ඡායාරූප, මාධ්ය සහ දැනුම්දීම් බෙදා ගනී"</string>
<string name="profile_name_generic" msgid="6851028682723034988">"උපාංගය"</string>
<string name="summary_generic" msgid="2346762210105903720"></string>
<string name="consent_yes" msgid="8344487259618762872">"ඉඩ දෙන්න"</string>
<string name="consent_no" msgid="2640796915611404382">"ඉඩ නොදෙන්න"</string>
+ <string name="consent_ok" msgid="3662376764371001106">"හරි"</string>
<string name="permission_sync_confirmation_title" msgid="667074294393493186">"ඔබගේ ඔරලෝසුවට යෙදුම් අවසර මාරු කිරීම"</string>
<string name="permission_sync_summary" msgid="8873391306499120778">"ඔබගේ ඔරලෝසුව පිහිටුවීම පහසු කිරීමට, පිහිටුවීමේදී ඔබගේ ඔරලෝසුවේ ස්ථාපනය කර ඇති යෙදුම් ඔබගේ දුරකථනයට සමාන අවසර භාවිත කරනු ඇත.\n\n මෙම අවසරවලට ඔබගේ ඔරලෝසුවේ මයික්රෆෝනයට සහ ස්ථානයට ප්රවේශය ඇතුළත් විය හැකිය."</string>
</resources>
diff --git a/packages/CompanionDeviceManager/res/values-sk/strings.xml b/packages/CompanionDeviceManager/res/values-sk/strings.xml
index dd75ef5..167eac8 100644
--- a/packages/CompanionDeviceManager/res/values-sk/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-sk/strings.xml
@@ -22,18 +22,30 @@
<string name="chooser_title" msgid="2262294130493605839">"Vyberte profil <xliff:g id="PROFILE_NAME">%1$s</xliff:g>, ktorý bude spravovať aplikácia <strong><xliff:g id="APP_NAME">%2$s</xliff:g></strong>"</string>
<string name="summary_watch" product="default" msgid="7113724443198337683">"<xliff:g id="APP_NAME">%1$s</xliff:g> bude môcť interagovať s vašimi upozorneniami a získavať prístup k povoleniam telefónu, SMS, kontaktov a kalendára."</string>
<string name="summary_watch" product="tablet" msgid="7113724443198337683">"<xliff:g id="APP_NAME">%1$s</xliff:g> bude môcť interagovať s vašimi upozorneniami a získavať prístup k povoleniam telefónu, SMS, kontaktov a kalendára."</string>
- <string name="title_app_streaming" msgid="4459136600249308574">"Chcete aplikácii <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> povoliť streamovanie aplikácií?"</string>
+ <string name="permission_apps" msgid="6142133265286656158">"Aplikácie"</string>
+ <string name="permission_apps_summary" msgid="798718816711515431">"Streamujte aplikácie telefónu"</string>
+ <string name="title_app_streaming" msgid="2270331024626446950">"Povoľte aplikácii <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> prístup k týmto informáciám z vášho telefónu"</string>
<string name="summary_app_streaming" product="default" msgid="6105916810614498138">"Povoľte aplikácii <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> vzdialený prístup k telefónu <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong>, aby mala po pripojení prístup k aplikáciám, ktoré sú v ňom nainštalované."</string>
<string name="summary_app_streaming" product="tablet" msgid="2996373715966272792">"Povoľte aplikácii <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> vzdialený prístup k tabletu <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong>, aby mala po pripojení prístup k aplikáciám, ktoré sú v ňom nainštalované."</string>
<string name="summary_app_streaming" product="device" msgid="7614171699434639963">"Povoľte aplikácii <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> vzdialený prístup k zariadeniu <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong>, aby mala po pripojení prístup k aplikáciám, ktoré sú v ňom nainštalované."</string>
+ <string name="helper_title_app_streaming" msgid="4151687003439969765">"Služby pre viacero zariadení"</string>
+ <string name="helper_summary_app_streaming" msgid="5344341720432827388">"Pomocou tejto služby sa streamujú aplikácie medzi vašimi zariadeniami"</string>
<string name="title_automotive_projection" msgid="3296005598978412847"></string>
<string name="summary_automotive_projection" msgid="8683801274662496164"></string>
<string name="title_computer" msgid="4693714143506569253">"Povoľte aplikácii <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> prístup k týmto informáciám z vášho telefónu"</string>
<string name="summary_computer" msgid="3798467601598297062"></string>
+ <string name="permission_notification" msgid="693762568127741203">"Upozornenia"</string>
+ <string name="permission_notification_summary" msgid="4398672775023193663">"Môže čítať všetky upozornenia vrátane informácií, ako sú kontakty, správy a fotky"</string>
+ <string name="permission_storage" msgid="6831099350839392343">"Fotky a médiá"</string>
+ <string name="permission_storage_summary" msgid="3918240895519506417"></string>
+ <string name="helper_title_computer" msgid="4671071173916176037">"Služby Google Play"</string>
+ <string name="helper_summary_computer" product="default" msgid="467996390095403648">"Táto služba zdieľa fotky, médiá a upozornenia z vášho telefónu do iných zariadení"</string>
+ <string name="helper_summary_computer" product="tablet" msgid="467996390095403648">"Táto služba zdieľa fotky, médiá a upozornenia z vášho telefónu do iných zariadení"</string>
<string name="profile_name_generic" msgid="6851028682723034988">"zariadenie"</string>
<string name="summary_generic" msgid="2346762210105903720"></string>
<string name="consent_yes" msgid="8344487259618762872">"Povoliť"</string>
<string name="consent_no" msgid="2640796915611404382">"Nepovoliť"</string>
+ <string name="consent_ok" msgid="3662376764371001106">"OK"</string>
<string name="permission_sync_confirmation_title" msgid="667074294393493186">"Presun povolení aplikácie do hodiniek"</string>
<string name="permission_sync_summary" msgid="8873391306499120778">"V rámci zjednodušenia nastavenia hodiniek budú aplikácie nainštalované do hodiniek pri nastavovaní používať rovnaké povolenia ako váš telefón.\n\n Tieto povolenia môžu zahrnovať prístup k mikrofónu a polohe hodiniek."</string>
</resources>
diff --git a/packages/CompanionDeviceManager/res/values-sl/strings.xml b/packages/CompanionDeviceManager/res/values-sl/strings.xml
index 7cb5fb5..5b79582 100644
--- a/packages/CompanionDeviceManager/res/values-sl/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-sl/strings.xml
@@ -22,18 +22,30 @@
<string name="chooser_title" msgid="2262294130493605839">"Izbira naprave <xliff:g id="PROFILE_NAME">%1$s</xliff:g>, ki jo bo upravljala aplikacija <strong><xliff:g id="APP_NAME">%2$s</xliff:g></strong>"</string>
<string name="summary_watch" product="default" msgid="7113724443198337683">"Aplikaciji <xliff:g id="APP_NAME">%1$s</xliff:g> bosta omogočena interakcija z obvestili in dostop do dovoljenj za telefon, sporočila SMS, stike in koledar."</string>
<string name="summary_watch" product="tablet" msgid="7113724443198337683">"Aplikaciji <xliff:g id="APP_NAME">%1$s</xliff:g> bosta omogočena interakcija z obvestili in dostop do dovoljenj za telefon, sporočila SMS, stike in koledar."</string>
- <string name="title_app_streaming" msgid="4459136600249308574">"Želite aplikaciji <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> dovoliti pretočno predvajanje aplikacij?"</string>
+ <string name="permission_apps" msgid="6142133265286656158">"Aplikacije"</string>
+ <string name="permission_apps_summary" msgid="798718816711515431">"Pretočno predvajanje aplikacij telefona"</string>
+ <string name="title_app_streaming" msgid="2270331024626446950">"Dovolite, da <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> dostopa do teh podatkov v vašem telefonu."</string>
<string name="summary_app_streaming" product="default" msgid="6105916810614498138">"Aplikaciji <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> dovoli oddaljen dostop do telefona <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong> za dostop do aplikacij, nameščenih v tem telefonu, ko je povezan v internet."</string>
<string name="summary_app_streaming" product="tablet" msgid="2996373715966272792">"Aplikaciji <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> dovoli oddaljen dostop do tabličnega računalnika <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong> za dostop do aplikacij, nameščenih v tem tabličnem računalniku, ko je povezan v internet."</string>
<string name="summary_app_streaming" product="device" msgid="7614171699434639963">"Aplikaciji <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> dovoli oddaljen dostop do naprave <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong> za dostop do aplikacij, nameščenih v tej napravi, ko je povezana v internet."</string>
+ <string name="helper_title_app_streaming" msgid="4151687003439969765">"Storitve za zunanje naprave"</string>
+ <string name="helper_summary_app_streaming" msgid="5344341720432827388">"Ta storitev se uporablja za pretočno predvajanje aplikacij med napravami."</string>
<string name="title_automotive_projection" msgid="3296005598978412847"></string>
<string name="summary_automotive_projection" msgid="8683801274662496164"></string>
<string name="title_computer" msgid="4693714143506569253">"Dovolite, da <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> dostopa do teh podatkov v vašem telefonu."</string>
<string name="summary_computer" msgid="3798467601598297062"></string>
+ <string name="permission_notification" msgid="693762568127741203">"Obvestila"</string>
+ <string name="permission_notification_summary" msgid="4398672775023193663">"Lahko bere vsa obvestila, vključno s podatki, kot so pogodbe, sporočila in fotografije."</string>
+ <string name="permission_storage" msgid="6831099350839392343">"Fotografije in predstavnost"</string>
+ <string name="permission_storage_summary" msgid="3918240895519506417"></string>
+ <string name="helper_title_computer" msgid="4671071173916176037">"Storitve Google Play"</string>
+ <string name="helper_summary_computer" product="default" msgid="467996390095403648">"Ta storitev deli fotografije, predstavnost in obvestila v telefonu z drugimi napravami."</string>
+ <string name="helper_summary_computer" product="tablet" msgid="467996390095403648">"Ta storitev deli fotografije, predstavnost in obvestila v telefonu z drugimi napravami."</string>
<string name="profile_name_generic" msgid="6851028682723034988">"naprava"</string>
<string name="summary_generic" msgid="2346762210105903720"></string>
<string name="consent_yes" msgid="8344487259618762872">"Dovoli"</string>
<string name="consent_no" msgid="2640796915611404382">"Ne dovoli"</string>
+ <string name="consent_ok" msgid="3662376764371001106">"V redu"</string>
<string name="permission_sync_confirmation_title" msgid="667074294393493186">"Prenos dovoljenj za aplikacije v uro"</string>
<string name="permission_sync_summary" msgid="8873391306499120778">"Za lažjo nastavitev ure bodo aplikacije, ki so bile med nastavljanjem nameščene v uri, uporabljale enaka dovoljenja kot tiste v telefonu.\n\n Ta dovoljenja lahko vključujejo dostop do mikrofona in lokacije ure."</string>
</resources>
diff --git a/packages/CompanionDeviceManager/res/values-sq/strings.xml b/packages/CompanionDeviceManager/res/values-sq/strings.xml
index 62c711a..b69fa8a 100644
--- a/packages/CompanionDeviceManager/res/values-sq/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-sq/strings.xml
@@ -22,18 +22,30 @@
<string name="chooser_title" msgid="2262294130493605839">"Zgjidh një profil <xliff:g id="PROFILE_NAME">%1$s</xliff:g> që do të menaxhohet nga <strong><xliff:g id="APP_NAME">%2$s</xliff:g></strong>"</string>
<string name="summary_watch" product="default" msgid="7113724443198337683">"<xliff:g id="APP_NAME">%1$s</xliff:g> do të lejohet të ndërveprojë me njoftimet e tua dhe të ketë qasje te lejet e \"Telefonit\", \"SMS-ve\", \"Kontakteve\" dhe \"Kalendarit\"."</string>
<string name="summary_watch" product="tablet" msgid="7113724443198337683">"<xliff:g id="APP_NAME">%1$s</xliff:g> do të lejohet të ndërveprojë me njoftimet e tua dhe të ketë qasje te lejet e \"Telefonit\", \"SMS-ve\", \"Kontakteve\" dhe \"Kalendarit\"."</string>
- <string name="title_app_streaming" msgid="4459136600249308574">"Të lejohet që <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> të transmetojë aplikacionet?"</string>
+ <string name="permission_apps" msgid="6142133265286656158">"Aplikacionet"</string>
+ <string name="permission_apps_summary" msgid="798718816711515431">"Transmeto aplikacionet e telefonit tënd"</string>
+ <string name="title_app_streaming" msgid="2270331024626446950">"Lejo që <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> të ketë qasje në këtë informacion nga telefoni yt"</string>
<string name="summary_app_streaming" product="default" msgid="6105916810614498138">"Lejo që <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> të ofrojë <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong> qasje në distancë për të pasur qasje në aplikacionet e instaluara në këtë telefon kur lidhet."</string>
<string name="summary_app_streaming" product="tablet" msgid="2996373715966272792">"Lejo që <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> të ofrojë <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong> qasje në distancë për të pasur qasje në aplikacionet e instaluara në këtë tablet kur lidhet."</string>
<string name="summary_app_streaming" product="device" msgid="7614171699434639963">"Lejo që <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> t\'i ofrojë <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong> qasje në distancë për të pasur qasje në aplikacionet e instaluara në këtë pajisje kur lidhet."</string>
+ <string name="helper_title_app_streaming" msgid="4151687003439969765">"Shërbimet mes pajisjeve"</string>
+ <string name="helper_summary_app_streaming" msgid="5344341720432827388">"Ky shërbim përdoret për të transmetuar aplikacione mes pajisjeve të tua"</string>
<string name="title_automotive_projection" msgid="3296005598978412847"></string>
<string name="summary_automotive_projection" msgid="8683801274662496164"></string>
<string name="title_computer" msgid="4693714143506569253">"Lejo që <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> të ketë qasje në këtë informacion nga telefoni yt"</string>
<string name="summary_computer" msgid="3798467601598297062"></string>
+ <string name="permission_notification" msgid="693762568127741203">"Njoftimet"</string>
+ <string name="permission_notification_summary" msgid="4398672775023193663">"Mund të lexojë të gjitha njoftimet, duke përfshirë informacione si kontaktet, mesazhet dhe fotografitë"</string>
+ <string name="permission_storage" msgid="6831099350839392343">"Fotografitë dhe media"</string>
+ <string name="permission_storage_summary" msgid="3918240895519506417"></string>
+ <string name="helper_title_computer" msgid="4671071173916176037">"Shërbimet e Google Play"</string>
+ <string name="helper_summary_computer" product="default" msgid="467996390095403648">"Ky shërbim ndan fotografitë, median dhe njoftimet nga telefoni yt te pajisjet e tjera"</string>
+ <string name="helper_summary_computer" product="tablet" msgid="467996390095403648">"Ky shërbim ndan fotografitë, median dhe njoftimet nga telefoni yt te pajisjet e tjera"</string>
<string name="profile_name_generic" msgid="6851028682723034988">"pajisja"</string>
<string name="summary_generic" msgid="2346762210105903720"></string>
<string name="consent_yes" msgid="8344487259618762872">"Lejo"</string>
<string name="consent_no" msgid="2640796915611404382">"Mos lejo"</string>
+ <string name="consent_ok" msgid="3662376764371001106">"Në rregull"</string>
<string name="permission_sync_confirmation_title" msgid="667074294393493186">"Transfero lejet e aplikacionit te ora jote"</string>
<string name="permission_sync_summary" msgid="8873391306499120778">"Për ta bërë më të lehtë konfigurimin e orës, aplikacionet e instaluara në orën tënde gjatë konfigurimit do të përdorin të njëjtat leje si telefoni yt.\n\n Këto leje mund të përfshijnë qasje në mikrofonin dhe vendndodhjen e orës."</string>
</resources>
diff --git a/packages/CompanionDeviceManager/res/values-sr/strings.xml b/packages/CompanionDeviceManager/res/values-sr/strings.xml
index 8d51c62..d40a112 100644
--- a/packages/CompanionDeviceManager/res/values-sr/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-sr/strings.xml
@@ -22,18 +22,30 @@
<string name="chooser_title" msgid="2262294130493605839">"Одаберите профил <xliff:g id="PROFILE_NAME">%1$s</xliff:g> којим ће управљати апликација <strong><xliff:g id="APP_NAME">%2$s</xliff:g></strong>"</string>
<string name="summary_watch" product="default" msgid="7113724443198337683">"<xliff:g id="APP_NAME">%1$s</xliff:g> ће добити дозволу за интеракцију са обавештењима и приступ дозволама за телефон, SMS поруке, контакте и календар."</string>
<string name="summary_watch" product="tablet" msgid="7113724443198337683">"<xliff:g id="APP_NAME">%1$s</xliff:g> ће добити дозволу за интеракцију са обавештењима и приступ дозволама за телефон, SMS поруке, контакте и календар."</string>
- <string name="title_app_streaming" msgid="4459136600249308574">"Желите да дозволите апликацији <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> да стримује апликације?"</string>
+ <string name="permission_apps" msgid="6142133265286656158">"Апликације"</string>
+ <string name="permission_apps_summary" msgid="798718816711515431">"Стримујте апликације на телефону"</string>
+ <string name="title_app_streaming" msgid="2270331024626446950">"Дозволите да <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> приступа овим информацијама са телефона"</string>
<string name="summary_app_streaming" product="default" msgid="6105916810614498138">"Дозволите апликацији <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> да даљински приступа апликацијама инсталираним на телефону <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong> када је повезан."</string>
<string name="summary_app_streaming" product="tablet" msgid="2996373715966272792">"Дозволите апликацији <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> да даљински приступа апликацијама инсталираним на таблету <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong> када је повезан."</string>
<string name="summary_app_streaming" product="device" msgid="7614171699434639963">"Дозволите апликацији <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> да даљински приступа апликацијама инсталираним на уређају <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong> када је повезан."</string>
+ <string name="helper_title_app_streaming" msgid="4151687003439969765">"Услуге на више уређаја"</string>
+ <string name="helper_summary_app_streaming" msgid="5344341720432827388">"Ова услуга се користи за стримовање апликација између уређаја"</string>
<string name="title_automotive_projection" msgid="3296005598978412847"></string>
<string name="summary_automotive_projection" msgid="8683801274662496164"></string>
<string name="title_computer" msgid="4693714143506569253">"Дозволите да <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> приступа овим информацијама са телефона"</string>
<string name="summary_computer" msgid="3798467601598297062"></string>
+ <string name="permission_notification" msgid="693762568127741203">"Обавештења"</string>
+ <string name="permission_notification_summary" msgid="4398672775023193663">"Може да чита сва обавештења, укључујући информације попут уговора, порука и слика"</string>
+ <string name="permission_storage" msgid="6831099350839392343">"Слике и медији"</string>
+ <string name="permission_storage_summary" msgid="3918240895519506417"></string>
+ <string name="helper_title_computer" msgid="4671071173916176037">"Google Play услуге"</string>
+ <string name="helper_summary_computer" product="default" msgid="467996390095403648">"Ова услуга дели слике, медијски садржај и обавештења са телефона на друге уређаје"</string>
+ <string name="helper_summary_computer" product="tablet" msgid="467996390095403648">"Ова услуга дели слике, медијски садржај и обавештења са телефона на друге уређаје"</string>
<string name="profile_name_generic" msgid="6851028682723034988">"уређај"</string>
<string name="summary_generic" msgid="2346762210105903720"></string>
<string name="consent_yes" msgid="8344487259618762872">"Дозволи"</string>
<string name="consent_no" msgid="2640796915611404382">"Не дозволи"</string>
+ <string name="consent_ok" msgid="3662376764371001106">"Потврди"</string>
<string name="permission_sync_confirmation_title" msgid="667074294393493186">"Пренесите дозволе за апликације на сат"</string>
<string name="permission_sync_summary" msgid="8873391306499120778">"Да бисмо поједноставили подешавање сата, апликације инсталиране на сату током подешавања ће користити исте дозволе као телефон.\n\n Те дозволе могу да обухватају приступ микрофону и локацији сата."</string>
</resources>
diff --git a/packages/CompanionDeviceManager/res/values-sv/strings.xml b/packages/CompanionDeviceManager/res/values-sv/strings.xml
index ca1ec87..fff01ed 100644
--- a/packages/CompanionDeviceManager/res/values-sv/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-sv/strings.xml
@@ -22,18 +22,30 @@
<string name="chooser_title" msgid="2262294130493605839">"Välj en <xliff:g id="PROFILE_NAME">%1$s</xliff:g> för hantering av <strong><xliff:g id="APP_NAME">%2$s</xliff:g></strong>"</string>
<string name="summary_watch" product="default" msgid="7113724443198337683">"<xliff:g id="APP_NAME">%1$s</xliff:g> får behörighet att interagera med dina aviseringar och komma åt behörigheterna för Telefon, Sms, Kontakter och Kalender."</string>
<string name="summary_watch" product="tablet" msgid="7113724443198337683">"<xliff:g id="APP_NAME">%1$s</xliff:g> får behörighet att interagera med dina aviseringar och komma åt behörigheterna för Telefon, Sms, Kontakter och Kalender."</string>
- <string name="title_app_streaming" msgid="4459136600249308574">"Vill du tillåta att <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> streamar appar?"</string>
+ <string name="permission_apps" msgid="6142133265286656158">"Appar"</string>
+ <string name="permission_apps_summary" msgid="798718816711515431">"Streama telefonens appar"</string>
+ <string name="title_app_streaming" msgid="2270331024626446950">"Ge <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> åtkomstbehörighet till denna information på telefonen"</string>
<string name="summary_app_streaming" product="default" msgid="6105916810614498138">"Låt <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> ge <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong> fjärråtkomst till åt appar som är installerade på den här telefonen när den är ansluten."</string>
<string name="summary_app_streaming" product="tablet" msgid="2996373715966272792">"Låt <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> ge <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong> fjärråtkomst till appar som är installerade på den här surfplattan när den är ansluten."</string>
<string name="summary_app_streaming" product="device" msgid="7614171699434639963">"Låt <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> ge <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong> fjärråtkomst till appar som är installerade på den här enheten när den är ansluten."</string>
+ <string name="helper_title_app_streaming" msgid="4151687003439969765">"Tjänster för flera enheter"</string>
+ <string name="helper_summary_app_streaming" msgid="5344341720432827388">"Den här tjänsten används för att streama appar mellan dina enheter"</string>
<string name="title_automotive_projection" msgid="3296005598978412847"></string>
<string name="summary_automotive_projection" msgid="8683801274662496164"></string>
<string name="title_computer" msgid="4693714143506569253">"Ge <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> åtkomstbehörighet till denna information på telefonen"</string>
<string name="summary_computer" msgid="3798467601598297062"></string>
+ <string name="permission_notification" msgid="693762568127741203">"Aviseringar"</string>
+ <string name="permission_notification_summary" msgid="4398672775023193663">"Kan läsa alla aviseringar, inklusive information som kontakter, meddelanden och foton"</string>
+ <string name="permission_storage" msgid="6831099350839392343">"Foton och media"</string>
+ <string name="permission_storage_summary" msgid="3918240895519506417"></string>
+ <string name="helper_title_computer" msgid="4671071173916176037">"Google Play-tjänster"</string>
+ <string name="helper_summary_computer" product="default" msgid="467996390095403648">"Den här tjänsten delar foton, media och aviseringar från telefonen till andra enheter"</string>
+ <string name="helper_summary_computer" product="tablet" msgid="467996390095403648">"Den här tjänsten delar foton, media och aviseringar från telefonen till andra enheter"</string>
<string name="profile_name_generic" msgid="6851028682723034988">"enhet"</string>
<string name="summary_generic" msgid="2346762210105903720"></string>
<string name="consent_yes" msgid="8344487259618762872">"Tillåt"</string>
<string name="consent_no" msgid="2640796915611404382">"Tillåt inte"</string>
+ <string name="consent_ok" msgid="3662376764371001106">"OK"</string>
<string name="permission_sync_confirmation_title" msgid="667074294393493186">"Överför appbehörigheter till klockan"</string>
<string name="permission_sync_summary" msgid="8873391306499120778">"Appar som installeras på klockan under konfigureringen får samma behörigheter som de har på telefonen så att konfigureringen ska bli enklare.\n\n Behörigheterna kan omfatta åtkomst till klockans mikrofon och plats."</string>
</resources>
diff --git a/packages/CompanionDeviceManager/res/values-sw/strings.xml b/packages/CompanionDeviceManager/res/values-sw/strings.xml
index cf92600..2533a97 100644
--- a/packages/CompanionDeviceManager/res/values-sw/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-sw/strings.xml
@@ -22,18 +22,30 @@
<string name="chooser_title" msgid="2262294130493605839">"Chagua <xliff:g id="PROFILE_NAME">%1$s</xliff:g> ili idhibitiwe na <strong><xliff:g id="APP_NAME">%2$s</xliff:g></strong>"</string>
<string name="summary_watch" product="default" msgid="7113724443198337683">"<xliff:g id="APP_NAME">%1$s</xliff:g> itaruhusiwa kufikia arifa zako na kufikia ruhusa za Simu, SMS, Anwani na Kalenda yako."</string>
<string name="summary_watch" product="tablet" msgid="7113724443198337683">"<xliff:g id="APP_NAME">%1$s</xliff:g> itaruhusiwa kufikia arifa zako na kufikia ruhusa za Simu, SMS, Anwani na Kalenda yako."</string>
- <string name="title_app_streaming" msgid="4459136600249308574">"Ungependa kuruhusu <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> itiririshe programu?"</string>
+ <string name="permission_apps" msgid="6142133265286656158">"Programu"</string>
+ <string name="permission_apps_summary" msgid="798718816711515431">"Tiririsha programu za simu yako"</string>
+ <string name="title_app_streaming" msgid="2270331024626446950">"Ruhusu <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> ifikie maelezo haya kutoka kwenye simu yako"</string>
<string name="summary_app_streaming" product="default" msgid="6105916810614498138">"Ruhusu <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> iipe <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong> ufikiaji wa mbali wa programu zilizosakinishwa kwenye simu hii wakati imeunganishwa."</string>
<string name="summary_app_streaming" product="tablet" msgid="2996373715966272792">"Ruhusu <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> iipe <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong> ufikiaji wa mbali wa programu zilizosakinishwa kwenye kompyuta hii kibao wakati imeunganishwa."</string>
<string name="summary_app_streaming" product="device" msgid="7614171699434639963">"Ruhusu <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> iipe <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong> ufikiaji wa mbali wa programu zilizosakinishwa kwenye kifaa hiki wakati kimeunganishwa."</string>
+ <string name="helper_title_app_streaming" msgid="4151687003439969765">"Huduma za kifaa kilichounganishwa kwingine"</string>
+ <string name="helper_summary_app_streaming" msgid="5344341720432827388">"Huduma hii inatumika kutiririsha programu kati ya vifaa vyako"</string>
<string name="title_automotive_projection" msgid="3296005598978412847"></string>
<string name="summary_automotive_projection" msgid="8683801274662496164"></string>
<string name="title_computer" msgid="4693714143506569253">"Ruhusu <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> ifikie maelezo haya kutoka kwenye simu yako"</string>
<string name="summary_computer" msgid="3798467601598297062"></string>
+ <string name="permission_notification" msgid="693762568127741203">"Arifa"</string>
+ <string name="permission_notification_summary" msgid="4398672775023193663">"Inaweza kusoma arifa zote, ikiwa ni pamoja na maelezo kama vile mikataba, ujumbe na picha"</string>
+ <string name="permission_storage" msgid="6831099350839392343">"Picha na maudhui"</string>
+ <string name="permission_storage_summary" msgid="3918240895519506417"></string>
+ <string name="helper_title_computer" msgid="4671071173916176037">"Huduma za Google Play"</string>
+ <string name="helper_summary_computer" product="default" msgid="467996390095403648">"Huduma hii inashiriki picha, maudhui na arifa kutoka kwenye simu yako kwenda kwenye vifaa vingine"</string>
+ <string name="helper_summary_computer" product="tablet" msgid="467996390095403648">"Huduma hii inashiriki picha, maudhui na arifa kutoka kwenye simu yako kwenda kwenye vifaa vingine"</string>
<string name="profile_name_generic" msgid="6851028682723034988">"kifaa"</string>
<string name="summary_generic" msgid="2346762210105903720"></string>
<string name="consent_yes" msgid="8344487259618762872">"Ruhusu"</string>
<string name="consent_no" msgid="2640796915611404382">"Usiruhusu"</string>
+ <string name="consent_ok" msgid="3662376764371001106">"Sawa"</string>
<string name="permission_sync_confirmation_title" msgid="667074294393493186">"Hamishia idhini za programu kwenye saa yako"</string>
<string name="permission_sync_summary" msgid="8873391306499120778">"Ili kurahisisha kuweka mipangilio ya saa yako, programu ambazo zimesakinishwa kwenye saa yako wakati wa kuweka mipangilio zitatumia ruhusa sawa na zinazotumika kwenye simu yako.\n\n Ruhusa hizi huenda zikajumuisha ufikiaji wa maikrofoni ya saa yako na maelezo ya mahali ilipo saa yako."</string>
</resources>
diff --git a/packages/CompanionDeviceManager/res/values-ta/strings.xml b/packages/CompanionDeviceManager/res/values-ta/strings.xml
index b86ea1c..3f55444 100644
--- a/packages/CompanionDeviceManager/res/values-ta/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-ta/strings.xml
@@ -22,18 +22,30 @@
<string name="chooser_title" msgid="2262294130493605839">"<strong><xliff:g id="APP_NAME">%2$s</xliff:g></strong> ஆப்ஸ் நிர்வகிக்கக்கூடிய <xliff:g id="PROFILE_NAME">%1$s</xliff:g> ஐத் தேர்ந்தெடுங்கள்"</string>
<string name="summary_watch" product="default" msgid="7113724443198337683">"உங்கள் அறிவிப்புகளைப் பார்க்கவும் மொபைல், மெசேஜ், தொடர்புகள், கேலெண்டர் ஆகியவற்றை அணுகவும் <xliff:g id="APP_NAME">%1$s</xliff:g> ஆப்ஸுக்கு அனுமதி வழங்கப்படும்."</string>
<string name="summary_watch" product="tablet" msgid="7113724443198337683">"உங்கள் அறிவிப்புகளைப் பார்க்கவும் மொபைல், மெசேஜ், தொடர்புகள், கேலெண்டர் ஆகியவற்றை அணுகவும் <xliff:g id="APP_NAME">%1$s</xliff:g> ஆப்ஸுக்கு அனுமதி வழங்கப்படும்."</string>
- <string name="title_app_streaming" msgid="4459136600249308574">"ஆப்ஸை ஸ்ட்ரீம் செய்ய <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> ஆப்ஸை அனுமதிக்கவா?"</string>
+ <string name="permission_apps" msgid="6142133265286656158">"ஆப்ஸ்"</string>
+ <string name="permission_apps_summary" msgid="798718816711515431">"உங்கள் மொபைலின் ஆப்ஸை ஸ்ட்ரீம் செய்யலாம்"</string>
+ <string name="title_app_streaming" msgid="2270331024626446950">"மொபைலில் உள்ள இந்தத் தகவல்களை அணுக, <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> ஆப்ஸை அனுமதிக்கவும்"</string>
<string name="summary_app_streaming" product="default" msgid="6105916810614498138">"இணைக்கப்பட்டிருக்கும்போது இந்த மொபைலில் நிறுவப்பட்டிருக்கும் ஆப்ஸை அணுகுவதற்கான தொலைநிலை அணுகலை <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong> சாதனத்திற்கு வழங்க <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> ஆப்ஸை அனுமதிக்கும்."</string>
<string name="summary_app_streaming" product="tablet" msgid="2996373715966272792">"இணைக்கப்பட்டிருக்கும்போது இந்த டேப்லெட்டில் நிறுவப்பட்டிருக்கும் ஆப்ஸை அணுகுவதற்கான தொலைநிலை அணுகலை <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong> சாதனத்திற்கு வழங்க <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> ஆப்ஸை அனுமதிக்கும்."</string>
<string name="summary_app_streaming" product="device" msgid="7614171699434639963">"இணைக்கப்பட்டிருக்கும்போது இந்தச் சாதனத்தில் நிறுவப்பட்டிருக்கும் ஆப்ஸை அணுகுவதற்கான தொலைநிலை அணுகலை <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong> சாதனத்திற்கு வழங்க <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> ஆப்ஸை அனுமதிக்கும்."</string>
+ <string name="helper_title_app_streaming" msgid="4151687003439969765">"சாதனங்களுக்கு இடையேயான சேவைகள்"</string>
+ <string name="helper_summary_app_streaming" msgid="5344341720432827388">"உங்கள் சாதனங்களுக்கு இடையே ஆப்ஸை ஸ்ட்ரீம் செய்ய இந்தச் சேவை பயன்படுத்தப்படுகிறது"</string>
<string name="title_automotive_projection" msgid="3296005598978412847"></string>
<string name="summary_automotive_projection" msgid="8683801274662496164"></string>
<string name="title_computer" msgid="4693714143506569253">"உங்கள் மொபைலிலிருந்து இந்தத் தகவலை அணுக <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> ஆப்ஸை அனுமதியுங்கள்"</string>
<string name="summary_computer" msgid="3798467601598297062"></string>
+ <string name="permission_notification" msgid="693762568127741203">"அறிவிப்புகள்"</string>
+ <string name="permission_notification_summary" msgid="4398672775023193663">"ஒப்பந்தங்கள், மெசேஜ்கள், படங்கள் போன்ற தகவல்கள் உட்பட அனைத்து அறிவிப்புகளையும் படிக்க முடியும்"</string>
+ <string name="permission_storage" msgid="6831099350839392343">"படங்கள் மற்றும் மீடியா"</string>
+ <string name="permission_storage_summary" msgid="3918240895519506417"></string>
+ <string name="helper_title_computer" msgid="4671071173916176037">"Google Play சேவைகள்"</string>
+ <string name="helper_summary_computer" product="default" msgid="467996390095403648">"படங்கள், மீடியா, அறிவிப்புகள் ஆகியவற்றை உங்கள் மொபைலில் இருந்து பிற சாதனங்களுக்கு இந்தச் சேவை பகிர்கிறது"</string>
+ <string name="helper_summary_computer" product="tablet" msgid="467996390095403648">"படங்கள், மீடியா, அறிவிப்புகள் ஆகியவற்றை உங்கள் மொபைலில் இருந்து பிற சாதனங்களுக்கு இந்தச் சேவை பகிர்கிறது"</string>
<string name="profile_name_generic" msgid="6851028682723034988">"சாதனம்"</string>
<string name="summary_generic" msgid="2346762210105903720"></string>
<string name="consent_yes" msgid="8344487259618762872">"அனுமதி"</string>
<string name="consent_no" msgid="2640796915611404382">"அனுமதிக்க வேண்டாம்"</string>
+ <string name="consent_ok" msgid="3662376764371001106">"சரி"</string>
<string name="permission_sync_confirmation_title" msgid="667074294393493186">"ஆப்ஸ் அனுமதிகளை உங்கள் வாட்ச்சிற்கு மாற்றுதல்"</string>
<string name="permission_sync_summary" msgid="8873391306499120778">"உங்கள் வாட்ச் அமைவை எளிதாக்க, உங்கள் மொபைலில் வழங்கியுள்ள அனுமதிகளையே அமைவின்போது வாட்ச்சில் நிறுவப்பட்ட ஆப்ஸும் பயன்படுத்தும்.\n\n உங்கள் வாட்ச்சிலுள்ள மைக்ரோஃபோன், இருப்பிடம் ஆகியவற்றுக்கான அணுகலும் இந்த அனுமதிகளில் அடங்கக்கூடும்."</string>
</resources>
diff --git a/packages/CompanionDeviceManager/res/values-te/strings.xml b/packages/CompanionDeviceManager/res/values-te/strings.xml
index 73cf3e8..552834e 100644
--- a/packages/CompanionDeviceManager/res/values-te/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-te/strings.xml
@@ -22,18 +22,30 @@
<string name="chooser_title" msgid="2262294130493605839">"<strong><xliff:g id="APP_NAME">%2$s</xliff:g></strong> ద్వారా మేనేజ్ చేయబడటానికి ఒక <xliff:g id="PROFILE_NAME">%1$s</xliff:g>ను ఎంచుకోండి"</string>
<string name="summary_watch" product="default" msgid="7113724443198337683">"మీ నోటిఫికేషన్లతో ఇంటరాక్ట్ అవ్వడానికి ఇంకా మీ ఫోన్, SMS, కాంటాక్ట్లు, Calendar అనుమతులను యాక్సెస్ చేయడానికి <xliff:g id="APP_NAME">%1$s</xliff:g> అనుమతించబడుతుంది."</string>
<string name="summary_watch" product="tablet" msgid="7113724443198337683">"మీ నోటిఫికేషన్లతో ఇంటరాక్ట్ అవ్వడానికి ఇంకా మీ ఫోన్, SMS, కాంటాక్ట్లు, Calendar అనుమతులను యాక్సెస్ చేయడానికి <xliff:g id="APP_NAME">%1$s</xliff:g> అనుమతించబడుతుంది."</string>
- <string name="title_app_streaming" msgid="4459136600249308574">"యాప్లను స్ట్రీమ్ చేయడానికి <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong>ను అనుమతించాలా?"</string>
+ <string name="permission_apps" msgid="6142133265286656158">"యాప్లు"</string>
+ <string name="permission_apps_summary" msgid="798718816711515431">"మీ ఫోన్ యాప్లను స్ట్రీమ్ చేయండి"</string>
+ <string name="title_app_streaming" msgid="2270331024626446950">"మీ ఫోన్ నుండి ఈ సమాచారాన్ని యాక్సెస్ చేయడానికి <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> యాప్ను అనుమతించండి"</string>
<string name="summary_app_streaming" product="default" msgid="6105916810614498138">"కనెక్ట్ అయినప్పుడు ఈ ఫోన్లో ఇన్స్టాల్ చేయబడిన యాప్లను యాక్సెస్ చేయడానికి <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong> రిమోట్ యాక్సెస్ను అందించడానికి <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong>ను అనుమతించండి."</string>
<string name="summary_app_streaming" product="tablet" msgid="2996373715966272792">"కనెక్ట్ అయినప్పుడు ఈ టాబ్లెట్లో ఇన్స్టాల్ చేయబడిన యాప్లను యాక్సెస్ చేయడానికి <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong> రిమోట్ యాక్సెస్ను అందించడానికి <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong>ను అనుమతించండి."</string>
<string name="summary_app_streaming" product="device" msgid="7614171699434639963">"కనెక్ట్ అయినప్పుడు ఈ పరికరంలో ఇన్స్టాల్ చేయబడిన యాప్లను యాక్సెస్ చేయడానికి <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong> రిమోట్ యాక్సెస్ను అందించడానికి <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong>ను అనుమతించండి."</string>
+ <string name="helper_title_app_streaming" msgid="4151687003439969765">"క్రాస్-డివైజ్ సర్వీసులు"</string>
+ <string name="helper_summary_app_streaming" msgid="5344341720432827388">"మీ పరికరాల మధ్య యాప్లను స్ట్రీమ్ చేయడానికి ఈ సర్వీస్ ఉపయోగించబడుతుంది"</string>
<string name="title_automotive_projection" msgid="3296005598978412847"></string>
<string name="summary_automotive_projection" msgid="8683801274662496164"></string>
<string name="title_computer" msgid="4693714143506569253">"మీ ఫోన్ నుండి ఈ సమాచారాన్ని యాక్సెస్ చేయడానికి <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> యాప్ను అనుమతించండి"</string>
<string name="summary_computer" msgid="3798467601598297062"></string>
+ <string name="permission_notification" msgid="693762568127741203">"నోటిఫికేషన్లు"</string>
+ <string name="permission_notification_summary" msgid="4398672775023193663">"ఒప్పందాలు, మెసేజ్లు, ఫోటోల వంటి సమాచారంతో సహా అన్ని నోటిఫికేషన్లను చదవగలరు"</string>
+ <string name="permission_storage" msgid="6831099350839392343">"ఫోటోలు, మీడియా"</string>
+ <string name="permission_storage_summary" msgid="3918240895519506417"></string>
+ <string name="helper_title_computer" msgid="4671071173916176037">"Google Play సర్వీసులు"</string>
+ <string name="helper_summary_computer" product="default" msgid="467996390095403648">"ఈ సర్వీస్ మీ ఫోన్ నుండి ఇతర పరికరాలకు ఫోటోలు, మీడియా, ఇంకా నోటిఫికేషన్లను షేర్ చేస్తుంది"</string>
+ <string name="helper_summary_computer" product="tablet" msgid="467996390095403648">"ఈ సర్వీస్ మీ ఫోన్ నుండి ఇతర పరికరాలకు ఫోటోలు, మీడియా, ఇంకా నోటిఫికేషన్లను షేర్ చేస్తుంది"</string>
<string name="profile_name_generic" msgid="6851028682723034988">"పరికరం"</string>
<string name="summary_generic" msgid="2346762210105903720"></string>
<string name="consent_yes" msgid="8344487259618762872">"అనుమతించు"</string>
<string name="consent_no" msgid="2640796915611404382">"అనుమతించవద్దు"</string>
+ <string name="consent_ok" msgid="3662376764371001106">"సరే"</string>
<string name="permission_sync_confirmation_title" msgid="667074294393493186">"మీ వాచ్కు యాప్ అనుమతులను బదిలీ చేయండి"</string>
<string name="permission_sync_summary" msgid="8873391306499120778">"మీ వాచ్ను సెటప్ చేయడాన్ని సులభతరం చేయడానికి, సెటప్ సమయంలో మీ వాచ్లో ఇన్స్టాల్ చేయబడిన యాప్లు మీ ఫోన్లో యాప్లకు ఉన్న అవే అనుమతులను ఉపయోగిస్తాయి.\n\n ఈ అనుమతులతో మీ వాచ్ మైక్రోఫోన్, అలాగే లొకేషన్ కూడా ఉండవచ్చు."</string>
</resources>
diff --git a/packages/CompanionDeviceManager/res/values-th/strings.xml b/packages/CompanionDeviceManager/res/values-th/strings.xml
index 6f29346..c15ce03 100644
--- a/packages/CompanionDeviceManager/res/values-th/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-th/strings.xml
@@ -22,18 +22,30 @@
<string name="chooser_title" msgid="2262294130493605839">"เลือก<xliff:g id="PROFILE_NAME">%1$s</xliff:g>ที่จะให้มีการจัดการโดย <strong><xliff:g id="APP_NAME">%2$s</xliff:g></strong>"</string>
<string name="summary_watch" product="default" msgid="7113724443198337683">"<xliff:g id="APP_NAME">%1$s</xliff:g> จะได้รับอนุญาตให้โต้ตอบกับการแจ้งเตือนและได้รับสิทธิ์เข้าถึงโทรศัพท์, SMS, รายชื่อติดต่อ และปฏิทิน"</string>
<string name="summary_watch" product="tablet" msgid="7113724443198337683">"<xliff:g id="APP_NAME">%1$s</xliff:g> จะได้รับอนุญาตให้โต้ตอบกับการแจ้งเตือนและได้รับสิทธิ์เข้าถึงโทรศัพท์, SMS, รายชื่อติดต่อ และปฏิทิน"</string>
- <string name="title_app_streaming" msgid="4459136600249308574">"อนุญาตให้ <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> สตรีมแอปพลิเคชันใช่ไหม"</string>
+ <string name="permission_apps" msgid="6142133265286656158">"แอป"</string>
+ <string name="permission_apps_summary" msgid="798718816711515431">"สตรีมแอปของโทรศัพท์คุณ"</string>
+ <string name="title_app_streaming" msgid="2270331024626446950">"อนุญาตให้ <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> เข้าถึงข้อมูลนี้จากโทรศัพท์ของคุณ"</string>
<string name="summary_app_streaming" product="default" msgid="6105916810614498138">"อนุญาตให้ <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> มอบสิทธิ์เข้าถึงแอปพลิเคชันที่ติดตั้งในโทรศัพท์เครื่องนี้จากระยะไกลให้แก่ <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong> เมื่อมีการเชื่อมต่อ"</string>
<string name="summary_app_streaming" product="tablet" msgid="2996373715966272792">"อนุญาตให้ <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> มอบสิทธิ์เข้าถึงแอปพลิเคชันที่ติดตั้งในแท็บเล็ตเครื่องนี้จากระยะไกลให้แก่ <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong> เมื่อมีการเชื่อมต่อ"</string>
<string name="summary_app_streaming" product="device" msgid="7614171699434639963">"อนุญาตให้ <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> มอบสิทธิ์เข้าถึงแอปพลิเคชันที่ติดตั้งในอุปกรณ์เครื่องนี้จากระยะไกลให้แก่ <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong> เมื่อมีการเชื่อมต่อ"</string>
+ <string name="helper_title_app_streaming" msgid="4151687003439969765">"บริการหลายอุปกรณ์"</string>
+ <string name="helper_summary_app_streaming" msgid="5344341720432827388">"บริการนี้ใช้เพื่อสตรีมแอประหว่างอุปกรณ์"</string>
<string name="title_automotive_projection" msgid="3296005598978412847"></string>
<string name="summary_automotive_projection" msgid="8683801274662496164"></string>
<string name="title_computer" msgid="4693714143506569253">"อนุญาตให้ <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> เข้าถึงข้อมูลนี้จากโทรศัพท์ของคุณ"</string>
<string name="summary_computer" msgid="3798467601598297062"></string>
+ <string name="permission_notification" msgid="693762568127741203">"การแจ้งเตือน"</string>
+ <string name="permission_notification_summary" msgid="4398672775023193663">"สามารถอ่านการแจ้งเตือนทั้งหมด รวมถึงข้อมูลอย่าง รายชื่อผู้ติดต่อ ข้อความ และรูปภาพ"</string>
+ <string name="permission_storage" msgid="6831099350839392343">"รูปภาพและสื่อ"</string>
+ <string name="permission_storage_summary" msgid="3918240895519506417"></string>
+ <string name="helper_title_computer" msgid="4671071173916176037">"บริการ Google Play"</string>
+ <string name="helper_summary_computer" product="default" msgid="467996390095403648">"บริการนี้แชร์รูปภาพ สื่อ และการแจ้งเตือนจากโทรศัพท์กับอุปกรณ์อื่นๆ"</string>
+ <string name="helper_summary_computer" product="tablet" msgid="467996390095403648">"บริการนี้แชร์รูปภาพ สื่อ และการแจ้งเตือนจากโทรศัพท์กับอุปกรณ์อื่นๆ"</string>
<string name="profile_name_generic" msgid="6851028682723034988">"อุปกรณ์"</string>
<string name="summary_generic" msgid="2346762210105903720"></string>
<string name="consent_yes" msgid="8344487259618762872">"อนุญาต"</string>
<string name="consent_no" msgid="2640796915611404382">"ไม่อนุญาต"</string>
+ <string name="consent_ok" msgid="3662376764371001106">"ตกลง"</string>
<string name="permission_sync_confirmation_title" msgid="667074294393493186">"โอนสิทธิ์ของแอปไปยังนาฬิกา"</string>
<string name="permission_sync_summary" msgid="8873391306499120778">"แอปที่ติดตั้งในนาฬิการะหว่างการตั้งค่าจะใช้สิทธิ์เดียวกันกับโทรศัพท์เพื่อให้การตั้งค่านาฬิกาง่ายขึ้น\n\n สิทธิ์เหล่านี้อาจรวมการเข้าถึงไมโครโฟนและตำแหน่งของนาฬิกา"</string>
</resources>
diff --git a/packages/CompanionDeviceManager/res/values-tl/strings.xml b/packages/CompanionDeviceManager/res/values-tl/strings.xml
index e557a38..ee5ec16 100644
--- a/packages/CompanionDeviceManager/res/values-tl/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-tl/strings.xml
@@ -22,18 +22,30 @@
<string name="chooser_title" msgid="2262294130493605839">"Pumili ng <xliff:g id="PROFILE_NAME">%1$s</xliff:g> para pamahalaan ng <strong><xliff:g id="APP_NAME">%2$s</xliff:g></strong>"</string>
<string name="summary_watch" product="default" msgid="7113724443198337683">"Papayagan ang <xliff:g id="APP_NAME">%1$s</xliff:g> na makipag-ugnayan sa mga notification mo at ma-access ang iyong mga pahintulot sa Telepono, SMS, Mga Contact, at Kalendaryo."</string>
<string name="summary_watch" product="tablet" msgid="7113724443198337683">"Papayagan ang <xliff:g id="APP_NAME">%1$s</xliff:g> na makipag-ugnayan sa mga notification mo at ma-access ang iyong mga pahintulot sa Telepono, SMS, Mga Contact, at Kalendaryo."</string>
- <string name="title_app_streaming" msgid="4459136600249308574">"Payagan ang <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> na mag-stream ng mga application?"</string>
+ <string name="permission_apps" msgid="6142133265286656158">"Mga App"</string>
+ <string name="permission_apps_summary" msgid="798718816711515431">"I-stream ang mga app ng iyong telepono"</string>
+ <string name="title_app_streaming" msgid="2270331024626446950">"Payagan ang <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> na i-access ang impormasyong ito sa iyong telepono"</string>
<string name="summary_app_streaming" product="default" msgid="6105916810614498138">"Payagan ang <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> na bigyan ang <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong> ng malayuang access para ma-access ang mga application na naka-install sa teleponong ito kapag nakakonekta."</string>
<string name="summary_app_streaming" product="tablet" msgid="2996373715966272792">"Payagan ang <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> na bigyan ang <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong> ng malayuang access para ma-access ang mga application na naka-install sa tablet na ito kapag nakakonekta."</string>
<string name="summary_app_streaming" product="device" msgid="7614171699434639963">"Payagan ang <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> na bigyan ang <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong> ng malayuang access para ma-access ang mga application na naka-install sa device na ito kapag nakakonekta."</string>
+ <string name="helper_title_app_streaming" msgid="4151687003439969765">"Mga cross-device na serbisyo"</string>
+ <string name="helper_summary_app_streaming" msgid="5344341720432827388">"Ginagamit ang serbisyong ito para mag-stream ng mga app sa pagitan ng iyong mga device"</string>
<string name="title_automotive_projection" msgid="3296005598978412847"></string>
<string name="summary_automotive_projection" msgid="8683801274662496164"></string>
<string name="title_computer" msgid="4693714143506569253">"Payagan ang <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> na i-access ang impormasyon sa iyong telepono"</string>
<string name="summary_computer" msgid="3798467601598297062"></string>
+ <string name="permission_notification" msgid="693762568127741203">"Mga Notification"</string>
+ <string name="permission_notification_summary" msgid="4398672775023193663">"Mababasa ang lahat ng notification, kasama ang impormasyon gaya ng mga kontrata, mensahe, at larawan"</string>
+ <string name="permission_storage" msgid="6831099350839392343">"Mga larawan at media"</string>
+ <string name="permission_storage_summary" msgid="3918240895519506417"></string>
+ <string name="helper_title_computer" msgid="4671071173916176037">"Mga serbisyo ng Google Play"</string>
+ <string name="helper_summary_computer" product="default" msgid="467996390095403648">"Nagbabahagi ang serbisyong ito ng mga larawan, media, at notification mula sa iyong telepono patungo sa iba pang device"</string>
+ <string name="helper_summary_computer" product="tablet" msgid="467996390095403648">"Nagbabahagi ang serbisyong ito ng mga larawan, media, at notification mula sa iyong telepono patungo sa iba pang device"</string>
<string name="profile_name_generic" msgid="6851028682723034988">"device"</string>
<string name="summary_generic" msgid="2346762210105903720"></string>
<string name="consent_yes" msgid="8344487259618762872">"Payagan"</string>
<string name="consent_no" msgid="2640796915611404382">"Huwag payagan"</string>
+ <string name="consent_ok" msgid="3662376764371001106">"OK"</string>
<string name="permission_sync_confirmation_title" msgid="667074294393493186">"Ilipat sa iyong relo ang mga pahintulot sa app"</string>
<string name="permission_sync_summary" msgid="8873391306499120778">"Para gawing mas madali na i-set up ang iyong relo, gagamitin ng mga app na naka-install sa relo mo sa oras ng pag-set up ang mga pahintulot na ginagamit din sa iyong telepono.\n\n Posibleng kasama sa mga pahintulot na ito ang access sa mikropono at lokasyon ng iyong relo."</string>
</resources>
diff --git a/packages/CompanionDeviceManager/res/values-tr/strings.xml b/packages/CompanionDeviceManager/res/values-tr/strings.xml
index c75214b..07a5c2a 100644
--- a/packages/CompanionDeviceManager/res/values-tr/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-tr/strings.xml
@@ -22,18 +22,30 @@
<string name="chooser_title" msgid="2262294130493605839">"<strong><xliff:g id="APP_NAME">%2$s</xliff:g></strong> tarafından yönetilecek bir <xliff:g id="PROFILE_NAME">%1$s</xliff:g> seçin"</string>
<string name="summary_watch" product="default" msgid="7113724443198337683">"<xliff:g id="APP_NAME">%1$s</xliff:g> adlı uygulamanın bildirimlerinizle etkileşimde bulunup Telefon, SMS, Kişiler ve Takvim izinlerinize erişmesine izin verilir."</string>
<string name="summary_watch" product="tablet" msgid="7113724443198337683">"<xliff:g id="APP_NAME">%1$s</xliff:g> adlı uygulamanın bildirimlerinizle etkileşimde bulunup Telefon, SMS, Kişiler ve Takvim izinlerinize erişmesine izin verilir."</string>
- <string name="title_app_streaming" msgid="4459136600249308574">"<strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> uygulamasının, uygulamalarda akış gerçekleştirmesine izin verilsin mi?"</string>
+ <string name="permission_apps" msgid="6142133265286656158">"Uygulamalar"</string>
+ <string name="permission_apps_summary" msgid="798718816711515431">"Telefonunuzun uygulamalarını akışla aktarın"</string>
+ <string name="title_app_streaming" msgid="2270331024626446950">"<strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> uygulamasının, telefonunuzdaki bu bilgilere erişmesine izin verin"</string>
<string name="summary_app_streaming" product="default" msgid="6105916810614498138">"<strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> uygulamasının, internete bağlanan bu telefondaki yüklü uygulamalara erişebilmesi için <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong> adlı cihaza uzaktan erişim izni verin."</string>
<string name="summary_app_streaming" product="tablet" msgid="2996373715966272792">"<strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> uygulamasının, internete bağlanan bu tabletteki yüklü uygulamalara erişebilmesi için <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong> adlı cihaza uzaktan erişim izni verin."</string>
<string name="summary_app_streaming" product="device" msgid="7614171699434639963">"<strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> uygulamasının, internete bağlanan bu cihazdaki yüklü uygulamalara erişebilmesi için <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong> adlı cihaza uzaktan erişim izni verin."</string>
+ <string name="helper_title_app_streaming" msgid="4151687003439969765">"Cihazlar arası hizmetler"</string>
+ <string name="helper_summary_app_streaming" msgid="5344341720432827388">"Bu hizmet, cihazlarınız arasında uygulama aktarmak için kullanılır"</string>
<string name="title_automotive_projection" msgid="3296005598978412847"></string>
<string name="summary_automotive_projection" msgid="8683801274662496164"></string>
<string name="title_computer" msgid="4693714143506569253">"<strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> uygulamasının, telefonunuzdaki bu bilgilere erişmesine izin verin"</string>
<string name="summary_computer" msgid="3798467601598297062"></string>
+ <string name="permission_notification" msgid="693762568127741203">"Bildirimler"</string>
+ <string name="permission_notification_summary" msgid="4398672775023193663">"Kişiler, mesajlar ve fotoğraflar da dahil olmak üzere tüm bildirimleri okuyabilir"</string>
+ <string name="permission_storage" msgid="6831099350839392343">"Fotoğraflar ve medya"</string>
+ <string name="permission_storage_summary" msgid="3918240895519506417"></string>
+ <string name="helper_title_computer" msgid="4671071173916176037">"Google Play hizmetleri"</string>
+ <string name="helper_summary_computer" product="default" msgid="467996390095403648">"Bu hizmet, telefonunuzdaki fotoğraf, medya ve bildirimleri diğer cihazlarla paylaşır"</string>
+ <string name="helper_summary_computer" product="tablet" msgid="467996390095403648">"Bu hizmet, telefonunuzdaki fotoğraf, medya ve bildirimleri diğer cihazlarla paylaşır"</string>
<string name="profile_name_generic" msgid="6851028682723034988">"cihaz"</string>
<string name="summary_generic" msgid="2346762210105903720"></string>
<string name="consent_yes" msgid="8344487259618762872">"İzin ver"</string>
<string name="consent_no" msgid="2640796915611404382">"İzin verme"</string>
+ <string name="consent_ok" msgid="3662376764371001106">"Tamam"</string>
<string name="permission_sync_confirmation_title" msgid="667074294393493186">"Uygulama izinlerini saatinize aktarma"</string>
<string name="permission_sync_summary" msgid="8873391306499120778">"Kurulum sırasında saatinize yüklenen uygulamalar, saat kurulumunuzu kolaylaştırmak için telefonunuzla aynı izinleri kullanır.\n\n Saatinizin mikrofonuna ve konumuna erişim bu izinlere dahil olabilir."</string>
</resources>
diff --git a/packages/CompanionDeviceManager/res/values-uk/strings.xml b/packages/CompanionDeviceManager/res/values-uk/strings.xml
index 46a25b2..8ab5bf1 100644
--- a/packages/CompanionDeviceManager/res/values-uk/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-uk/strings.xml
@@ -22,18 +22,30 @@
<string name="chooser_title" msgid="2262294130493605839">"Виберіть <xliff:g id="PROFILE_NAME">%1$s</xliff:g>, яким керуватиме додаток <strong><xliff:g id="APP_NAME">%2$s</xliff:g></strong>"</string>
<string name="summary_watch" product="default" msgid="7113724443198337683">"Додаток <xliff:g id="APP_NAME">%1$s</xliff:g> зможе взаємодіяти з вашими сповіщеннями та отримає дозволи \"Телефон\", \"SMS\", \"Контакти\" й \"Календар\"."</string>
<string name="summary_watch" product="tablet" msgid="7113724443198337683">"Додаток <xliff:g id="APP_NAME">%1$s</xliff:g> зможе взаємодіяти з вашими сповіщеннями та отримає дозволи \"Телефон\", \"SMS\", \"Контакти\" й \"Календар\"."</string>
- <string name="title_app_streaming" msgid="4459136600249308574">"Дозволити додатку <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> транслювати інші додатки?"</string>
+ <string name="permission_apps" msgid="6142133265286656158">"Додатки"</string>
+ <string name="permission_apps_summary" msgid="798718816711515431">"Транслювати додатки телефона"</string>
+ <string name="title_app_streaming" msgid="2270331024626446950">"Надайте додатку <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> доступ до цієї інформації з телефона"</string>
<string name="summary_app_streaming" product="default" msgid="6105916810614498138">"Дозвольте додатку <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> за наявності з’єднання надавати пристрою <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong> віддалений доступ до додатків, установлених на цьому телефоні."</string>
<string name="summary_app_streaming" product="tablet" msgid="2996373715966272792">"Дозвольте додатку <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> за наявності з’єднання надавати пристрою <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong> віддалений доступ до додатків, установлених на цьому планшеті."</string>
<string name="summary_app_streaming" product="device" msgid="7614171699434639963">"Дозвольте додатку <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> за наявності з’єднання надавати пристрою <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong> віддалений доступ до додатків, установлених на цьому пристрої."</string>
+ <string name="helper_title_app_streaming" msgid="4151687003439969765">"Сервіси для кількох пристроїв"</string>
+ <string name="helper_summary_app_streaming" msgid="5344341720432827388">"Цей сервіс використовується для трансляції додатків між вашими пристроями"</string>
<string name="title_automotive_projection" msgid="3296005598978412847"></string>
<string name="summary_automotive_projection" msgid="8683801274662496164"></string>
<string name="title_computer" msgid="4693714143506569253">"Надайте додатку <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> доступ до цієї інформації з телефона"</string>
<string name="summary_computer" msgid="3798467601598297062"></string>
+ <string name="permission_notification" msgid="693762568127741203">"Сповіщення"</string>
+ <string name="permission_notification_summary" msgid="4398672775023193663">"Може читати всі сповіщення, зокрема таку інформацію, як контакти, повідомлення та фотографії"</string>
+ <string name="permission_storage" msgid="6831099350839392343">"Фотографії та медіафайли"</string>
+ <string name="permission_storage_summary" msgid="3918240895519506417"></string>
+ <string name="helper_title_computer" msgid="4671071173916176037">"Сервіси Google Play"</string>
+ <string name="helper_summary_computer" product="default" msgid="467996390095403648">"Цей сервіс передає фотографії, медіафайли та сповіщення з вашого телефона на інші пристрої"</string>
+ <string name="helper_summary_computer" product="tablet" msgid="467996390095403648">"Цей сервіс передає фотографії, медіафайли та сповіщення з вашого телефона на інші пристрої"</string>
<string name="profile_name_generic" msgid="6851028682723034988">"пристрій"</string>
<string name="summary_generic" msgid="2346762210105903720"></string>
<string name="consent_yes" msgid="8344487259618762872">"Дозволити"</string>
<string name="consent_no" msgid="2640796915611404382">"Не дозволяти"</string>
+ <string name="consent_ok" msgid="3662376764371001106">"OK"</string>
<string name="permission_sync_confirmation_title" msgid="667074294393493186">"Перенести дозволи для додатків на годинник"</string>
<string name="permission_sync_summary" msgid="8873391306499120778">"Задля зручності додатки, установлені на годиннику протягом налаштування, використовуватимуть ті самі дозволи, що й на телефоні.\n\n До таких дозволів може належати доступ до мікрофона й геоданих годинника."</string>
</resources>
diff --git a/packages/CompanionDeviceManager/res/values-ur/strings.xml b/packages/CompanionDeviceManager/res/values-ur/strings.xml
index c9f930f..0c36865 100644
--- a/packages/CompanionDeviceManager/res/values-ur/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-ur/strings.xml
@@ -22,18 +22,30 @@
<string name="chooser_title" msgid="2262294130493605839">"<strong><xliff:g id="APP_NAME">%2$s</xliff:g></strong> کے ذریعے نظم کئے جانے کیلئے <xliff:g id="PROFILE_NAME">%1$s</xliff:g> کو منتخب کریں"</string>
<string name="summary_watch" product="default" msgid="7113724443198337683">"<xliff:g id="APP_NAME">%1$s</xliff:g> کو آپ کی اطلاعات کے ساتھ تعامل کرنے اور آپ کے فون، SMS، رابطوں اور کیلنڈر کی اجازتوں تک رسائی کی اجازت ہوگی۔"</string>
<string name="summary_watch" product="tablet" msgid="7113724443198337683">"<xliff:g id="APP_NAME">%1$s</xliff:g> کو آپ کی اطلاعات کے ساتھ تعامل کرنے اور آپ کے فون، SMS، رابطوں اور کیلنڈر کی اجازتوں تک رسائی کی اجازت ہوگی۔"</string>
- <string name="title_app_streaming" msgid="4459136600249308574">"<strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> کو ایپلیکیشنز کی سلسلہ بندی کرنے کی اجازت دیں؟"</string>
+ <string name="permission_apps" msgid="6142133265286656158">"ایپس"</string>
+ <string name="permission_apps_summary" msgid="798718816711515431">"اپنے فون کی ایپس کی سلسلہ بندی کریں"</string>
+ <string name="title_app_streaming" msgid="2270331024626446950">"<strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> کو اپنے فون سے ان معلومات تک رسائی حاصل کرنے کی اجازت دیں"</string>
<string name="summary_app_streaming" product="default" msgid="6105916810614498138">"منسلک ہونے پر، اس فون پر انسٹال کردہ ایپلیکیشنز تک رسائی حاصل کرنے کے لیے <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> کو <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong> کے لیے ریموٹ تک رسائی فراہم کرنے کی اجازت دیں۔"</string>
<string name="summary_app_streaming" product="tablet" msgid="2996373715966272792">"منسلک ہونے پر، اس ٹیبلیٹ پر انسٹال کردہ ایپلیکیشنز تک رسائی حاصل کرنے کے لیے <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> کو <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong> کے لیے ریموٹ تک رسائی فراہم کرنے کی اجازت دیں۔"</string>
<string name="summary_app_streaming" product="device" msgid="7614171699434639963">"منسلک ہونے پر، اس آلے پر انسٹال کردہ ایپلیکیشنز تک رسائی حاصل کرنے کے لیے <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> کو <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong> کے لیے ریموٹ تک رسائی فراہم کرنے کی اجازت دیں۔"</string>
+ <string name="helper_title_app_streaming" msgid="4151687003439969765">"کراس آلے کی سروس"</string>
+ <string name="helper_summary_app_streaming" msgid="5344341720432827388">"یہ سروس آپ کے آلات کے درمیان ایپس کو اسٹریم کرنے کے لیے استعمال ہوتی ہے"</string>
<string name="title_automotive_projection" msgid="3296005598978412847"></string>
<string name="summary_automotive_projection" msgid="8683801274662496164"></string>
<string name="title_computer" msgid="4693714143506569253">"اپنے فون سے اس معلومات تک رسائی حاصل Allow <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> کرنے کی اجازت دیں"</string>
<string name="summary_computer" msgid="3798467601598297062"></string>
+ <string name="permission_notification" msgid="693762568127741203">"اطلاعات"</string>
+ <string name="permission_notification_summary" msgid="4398672775023193663">"معاہدوں، پیغامات اور تصاویر جیسی معلومات سمیت تمام اطلاعات پڑھ سکتے ہیں"</string>
+ <string name="permission_storage" msgid="6831099350839392343">"تصاویر اور میڈیا"</string>
+ <string name="permission_storage_summary" msgid="3918240895519506417"></string>
+ <string name="helper_title_computer" msgid="4671071173916176037">"Google Play سروسز"</string>
+ <string name="helper_summary_computer" product="default" msgid="467996390095403648">"یہ سروس آپ کے فون سے دیگر آلات پر تصاویر، میڈیا اور اطلاعات کا اشتراک کرتی ہے"</string>
+ <string name="helper_summary_computer" product="tablet" msgid="467996390095403648">"یہ سروس آپ کے فون سے دیگر آلات پر تصاویر، میڈیا اور اطلاعات کا اشتراک کرتی ہے"</string>
<string name="profile_name_generic" msgid="6851028682723034988">"آلہ"</string>
<string name="summary_generic" msgid="2346762210105903720"></string>
<string name="consent_yes" msgid="8344487259618762872">"اجازت دیں"</string>
<string name="consent_no" msgid="2640796915611404382">"اجازت نہ دیں"</string>
+ <string name="consent_ok" msgid="3662376764371001106">"ٹھیک ہے"</string>
<string name="permission_sync_confirmation_title" msgid="667074294393493186">"اپنی گھڑی پر ایپ کی اجازتیں منتقل کریں"</string>
<string name="permission_sync_summary" msgid="8873391306499120778">"آپ کی گھڑی کو سیٹ اپ کرنے کے عمل کو زیادہ آسان بنانے کے لیے، سیٹ اپ کے دوران آپ کی گھڑی پر انسٹال کردہ ایپس انہیں اجازتوں کا استعمال کریں گی جن کا استعمال آپ کا فون کرتا ہے۔\n\n ان اجازتوں میں آپ کی گھڑی کے مائیکروفون اور مقام تک کی رسائی شامل ہو سکتی ہے۔"</string>
</resources>
diff --git a/packages/CompanionDeviceManager/res/values-uz/strings.xml b/packages/CompanionDeviceManager/res/values-uz/strings.xml
index 91fdd94..59fc98f 100644
--- a/packages/CompanionDeviceManager/res/values-uz/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-uz/strings.xml
@@ -22,18 +22,30 @@
<string name="chooser_title" msgid="2262294130493605839">"<strong><xliff:g id="APP_NAME">%2$s</xliff:g></strong> boshqaradigan <xliff:g id="PROFILE_NAME">%1$s</xliff:g> qurilmasini tanlang"</string>
<string name="summary_watch" product="default" msgid="7113724443198337683">"<xliff:g id="APP_NAME">%1$s</xliff:g> ilovasiga bildirishnomalar bilan ishlash va telefon, SMS, kontaktlar va taqvimga kirishga ruxsat beriladi"</string>
<string name="summary_watch" product="tablet" msgid="7113724443198337683">"<xliff:g id="APP_NAME">%1$s</xliff:g> ilovasiga bildirishnomalar bilan ishlash va telefon, SMS, kontaktlar va taqvimga kirishga ruxsat beriladi"</string>
- <string name="title_app_streaming" msgid="4459136600249308574">"<strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> ilovasiga ilovalarni strim qilishi uchun ruxsat berilsinmi?"</string>
+ <string name="permission_apps" msgid="6142133265286656158">"Ilovalar"</string>
+ <string name="permission_apps_summary" msgid="798718816711515431">"Telefondagi ilovalarni translatsiya qilish"</string>
+ <string name="title_app_streaming" msgid="2270331024626446950">"<strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> ilovasiga telefondagi ushbu maʼlumot uchun ruxsat bering"</string>
<string name="summary_app_streaming" product="default" msgid="6105916810614498138">"<strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> ilovasiga <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong> ulanganda ushbu telefonda oʻrnatilgan ilovalarga masofadan kirish ruxsatini bering."</string>
<string name="summary_app_streaming" product="tablet" msgid="2996373715966272792">"<strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> ilovasiga <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong> ulanganda ushbu planshetda oʻrnatilgan ilovalarga masofadan kirish ruxsatini bering."</string>
<string name="summary_app_streaming" product="device" msgid="7614171699434639963">"<strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> ilovasiga <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong> ulanganda ushbu qurilmada oʻrnatilgan ilovalarga masofadan kirish ruxsatini bering."</string>
+ <string name="helper_title_app_streaming" msgid="4151687003439969765">"Qurilmalararo xizmatlar"</string>
+ <string name="helper_summary_app_streaming" msgid="5344341720432827388">"Bu xizmat ilovalarni qurilmalararo translatsiya qilishda ishlatiladi"</string>
<string name="title_automotive_projection" msgid="3296005598978412847"></string>
<string name="summary_automotive_projection" msgid="8683801274662496164"></string>
<string name="title_computer" msgid="4693714143506569253">"<strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> ilovasiga telefondagi ushbu maʼlumot uchun ruxsat bering"</string>
<string name="summary_computer" msgid="3798467601598297062"></string>
+ <string name="permission_notification" msgid="693762568127741203">"Bildirishnomalar"</string>
+ <string name="permission_notification_summary" msgid="4398672775023193663">"Barcha bildirishnomalarni, jumladan, kontaktlar, xabarlar va suratlarni oʻqishi mumkin"</string>
+ <string name="permission_storage" msgid="6831099350839392343">"Suratlar va media"</string>
+ <string name="permission_storage_summary" msgid="3918240895519506417"></string>
+ <string name="helper_title_computer" msgid="4671071173916176037">"Google Play xizmatlari"</string>
+ <string name="helper_summary_computer" product="default" msgid="467996390095403648">"Bu xizmat telefondagi rasm, media va bildirishnomalarni boshqa qurilmalarga ulashadi"</string>
+ <string name="helper_summary_computer" product="tablet" msgid="467996390095403648">"Bu xizmat telefondagi rasm, media va bildirishnomalarni boshqa qurilmalarga ulashadi"</string>
<string name="profile_name_generic" msgid="6851028682723034988">"qurilma"</string>
<string name="summary_generic" msgid="2346762210105903720"></string>
<string name="consent_yes" msgid="8344487259618762872">"Ruxsat"</string>
<string name="consent_no" msgid="2640796915611404382">"Ruxsat berilmasin"</string>
+ <string name="consent_ok" msgid="3662376764371001106">"OK"</string>
<string name="permission_sync_confirmation_title" msgid="667074294393493186">"Ilova uchun ruxsatlarni soatingizga uzating"</string>
<string name="permission_sync_summary" msgid="8873391306499120778">"Soatingizni sozlashni qulaylashtirish maqsadida sozlash paytida soatingizga oʻrnatilgan ilovalar telefoningiz bilan bir xil ruxsatlardan foydalanadi.\n\n Bunday ruxsatlarga soatingiz mikrofoni va joylashuv axborotiga ruxsatlar kirishi mumkin."</string>
</resources>
diff --git a/packages/CompanionDeviceManager/res/values-vi/strings.xml b/packages/CompanionDeviceManager/res/values-vi/strings.xml
index 4f96bd4..8a96c4a 100644
--- a/packages/CompanionDeviceManager/res/values-vi/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-vi/strings.xml
@@ -22,18 +22,30 @@
<string name="chooser_title" msgid="2262294130493605839">"Chọn một <xliff:g id="PROFILE_NAME">%1$s</xliff:g> sẽ do <strong><xliff:g id="APP_NAME">%2$s</xliff:g></strong> quản lý"</string>
<string name="summary_watch" product="default" msgid="7113724443198337683">"<xliff:g id="APP_NAME">%1$s</xliff:g> sẽ được phép tương tác với thông báo cũng như truy cập vào Điện thoại, SMS, Danh bạ và Lịch."</string>
<string name="summary_watch" product="tablet" msgid="7113724443198337683">"<xliff:g id="APP_NAME">%1$s</xliff:g> sẽ được phép tương tác với thông báo cũng như truy cập vào Điện thoại, SMS, Danh bạ và Lịch."</string>
- <string name="title_app_streaming" msgid="4459136600249308574">"Cho phép <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> truyền trực tuyến ứng dụng?"</string>
+ <string name="permission_apps" msgid="6142133265286656158">"Ứng dụng"</string>
+ <string name="permission_apps_summary" msgid="798718816711515431">"Truyền các ứng dụng trên điện thoại của bạn"</string>
+ <string name="title_app_streaming" msgid="2270331024626446950">"Cho phép <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> truy cập vào thông tin này trên điện thoại của bạn"</string>
<string name="summary_app_streaming" product="default" msgid="6105916810614498138">"Cho phép <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> truy cập từ xa vào các ứng dụng đã cài đặt trên <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong> khi điện thoại này có kết nối."</string>
<string name="summary_app_streaming" product="tablet" msgid="2996373715966272792">"Cho phép <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> truy cập từ xa vào các ứng dụng đã cài đặt trên <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong> khi máy tính bảng này có kết nối."</string>
<string name="summary_app_streaming" product="device" msgid="7614171699434639963">"Cho phép <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> truy cập từ xa vào các ứng dụng đã cài đặt trên <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong> khi thiết bị này có kết nối."</string>
+ <string name="helper_title_app_streaming" msgid="4151687003439969765">"Dịch vụ trên nhiều thiết bị"</string>
+ <string name="helper_summary_app_streaming" msgid="5344341720432827388">"Dịch vụ này được dùng để truyền ứng dụng giữa các thiết bị"</string>
<string name="title_automotive_projection" msgid="3296005598978412847"></string>
<string name="summary_automotive_projection" msgid="8683801274662496164"></string>
<string name="title_computer" msgid="4693714143506569253">"Cho phép <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> truy cập vào thông tin này trên điện thoại của bạn"</string>
<string name="summary_computer" msgid="3798467601598297062"></string>
+ <string name="permission_notification" msgid="693762568127741203">"Thông báo"</string>
+ <string name="permission_notification_summary" msgid="4398672775023193663">"Có thể đọc tất cả các thông báo, kể cả những thông tin như hợp đồng, tin nhắn và ảnh"</string>
+ <string name="permission_storage" msgid="6831099350839392343">"Ảnh và nội dung nghe nhìn"</string>
+ <string name="permission_storage_summary" msgid="3918240895519506417"></string>
+ <string name="helper_title_computer" msgid="4671071173916176037">"Dịch vụ Google Play"</string>
+ <string name="helper_summary_computer" product="default" msgid="467996390095403648">"Dịch vụ này chia sẻ ảnh, nội dung nghe nhìn và thông báo từ điện thoại của bạn sang các thiết bị khác"</string>
+ <string name="helper_summary_computer" product="tablet" msgid="467996390095403648">"Dịch vụ này chia sẻ ảnh, nội dung nghe nhìn và thông báo từ điện thoại của bạn sang các thiết bị khác"</string>
<string name="profile_name_generic" msgid="6851028682723034988">"thiết bị"</string>
<string name="summary_generic" msgid="2346762210105903720"></string>
<string name="consent_yes" msgid="8344487259618762872">"Cho phép"</string>
<string name="consent_no" msgid="2640796915611404382">"Không cho phép"</string>
+ <string name="consent_ok" msgid="3662376764371001106">"OK"</string>
<string name="permission_sync_confirmation_title" msgid="667074294393493186">"Chuyển quyền cho ứng dụng sang đồng hồ"</string>
<string name="permission_sync_summary" msgid="8873391306499120778">"Để thiết lập đồng hồ dễ dàng hơn, trong quá trình thiết lập, các ứng dụng được cài đặt trên đồng hồ của bạn sẽ sử dụng các quyền giống như trên điện thoại.\n\n Các quyền này có thể bao gồm quyền sử dụng micrô và thông tin vị trí của đồng hồ."</string>
</resources>
diff --git a/packages/CompanionDeviceManager/res/values-zh-rCN/strings.xml b/packages/CompanionDeviceManager/res/values-zh-rCN/strings.xml
index 3fdccf2..1ee43c9 100644
--- a/packages/CompanionDeviceManager/res/values-zh-rCN/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-zh-rCN/strings.xml
@@ -22,18 +22,30 @@
<string name="chooser_title" msgid="2262294130493605839">"选择要由<strong><xliff:g id="APP_NAME">%2$s</xliff:g></strong>管理的<xliff:g id="PROFILE_NAME">%1$s</xliff:g>"</string>
<string name="summary_watch" product="default" msgid="7113724443198337683">"“<xliff:g id="APP_NAME">%1$s</xliff:g>”将能与通知互动,并可访问电话、短信、通讯录和日历。"</string>
<string name="summary_watch" product="tablet" msgid="7113724443198337683">"“<xliff:g id="APP_NAME">%1$s</xliff:g>”将能与通知互动,并可访问电话、短信、通讯录和日历。"</string>
- <string name="title_app_streaming" msgid="4459136600249308574">"是否允许 <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> 流式传输应用?"</string>
+ <string name="permission_apps" msgid="6142133265286656158">"应用"</string>
+ <string name="permission_apps_summary" msgid="798718816711515431">"流式传输手机的应用内容"</string>
+ <string name="title_app_streaming" msgid="2270331024626446950">"允许“<xliff:g id="APP_NAME">%1$s</xliff:g>”<strong></strong>访问您手机中的这项信息"</string>
<string name="summary_app_streaming" product="default" msgid="6105916810614498138">"在 <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong> 连接到网络后,允许 <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> 远程访问该手机上安装的应用。"</string>
<string name="summary_app_streaming" product="tablet" msgid="2996373715966272792">"在 <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong> 连接到网络后,允许 <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> 远程访问该平板电脑上安装的应用。"</string>
<string name="summary_app_streaming" product="device" msgid="7614171699434639963">"在 <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong> 连接到网络后,允许 <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> 远程访问该设备上安装的应用。"</string>
+ <string name="helper_title_app_streaming" msgid="4151687003439969765">"跨设备服务"</string>
+ <string name="helper_summary_app_streaming" msgid="5344341720432827388">"此服务用于在设备之间流式传输应用内容"</string>
<string name="title_automotive_projection" msgid="3296005598978412847"></string>
<string name="summary_automotive_projection" msgid="8683801274662496164"></string>
<string name="title_computer" msgid="4693714143506569253">"允许 <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> 访问您手机中的这项信息"</string>
<string name="summary_computer" msgid="3798467601598297062"></string>
+ <string name="permission_notification" msgid="693762568127741203">"通知"</string>
+ <string name="permission_notification_summary" msgid="4398672775023193663">"可以读取所有通知,包括合同、消息和照片等信息"</string>
+ <string name="permission_storage" msgid="6831099350839392343">"照片和媒体内容"</string>
+ <string name="permission_storage_summary" msgid="3918240895519506417"></string>
+ <string name="helper_title_computer" msgid="4671071173916176037">"Google Play 服务"</string>
+ <string name="helper_summary_computer" product="default" msgid="467996390095403648">"此服务可将您手机中的照片、媒体内容和通知分享给其他设备"</string>
+ <string name="helper_summary_computer" product="tablet" msgid="467996390095403648">"此服务可将您手机中的照片、媒体内容和通知分享给其他设备"</string>
<string name="profile_name_generic" msgid="6851028682723034988">"设备"</string>
<string name="summary_generic" msgid="2346762210105903720"></string>
<string name="consent_yes" msgid="8344487259618762872">"允许"</string>
<string name="consent_no" msgid="2640796915611404382">"不允许"</string>
+ <string name="consent_ok" msgid="3662376764371001106">"确定"</string>
<string name="permission_sync_confirmation_title" msgid="667074294393493186">"将应用权限转让给手表"</string>
<string name="permission_sync_summary" msgid="8873391306499120778">"为了让您更轻松地设置手表,在设置过程中安装在手表上的应用将使用与手机相同的权限。\n\n这些权限可能包括使用手表的麦克风和位置信息。"</string>
</resources>
diff --git a/packages/CompanionDeviceManager/res/values-zh-rHK/strings.xml b/packages/CompanionDeviceManager/res/values-zh-rHK/strings.xml
index a4dc0c9..fa2f0fc 100644
--- a/packages/CompanionDeviceManager/res/values-zh-rHK/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-zh-rHK/strings.xml
@@ -22,18 +22,30 @@
<string name="chooser_title" msgid="2262294130493605839">"選擇由 <strong><xliff:g id="APP_NAME">%2$s</xliff:g></strong> 管理的<xliff:g id="PROFILE_NAME">%1$s</xliff:g>"</string>
<string name="summary_watch" product="default" msgid="7113724443198337683">"「<xliff:g id="APP_NAME">%1$s</xliff:g>」將可存取通知、電話、短訊、聯絡人和日曆資料。"</string>
<string name="summary_watch" product="tablet" msgid="7113724443198337683">"「<xliff:g id="APP_NAME">%1$s</xliff:g>」將可存取通知、電話、短訊、聯絡人和日曆資料。"</string>
- <string name="title_app_streaming" msgid="4459136600249308574">"要允許「<xliff:g id="APP_NAME">%1$s</xliff:g>」<strong></strong>串流播放應用程式的內容嗎?"</string>
+ <string name="permission_apps" msgid="6142133265286656158">"應用程式"</string>
+ <string name="permission_apps_summary" msgid="798718816711515431">"串流播放手機應用程式內容"</string>
+ <string name="title_app_streaming" msgid="2270331024626446950">"允許「<xliff:g id="APP_NAME">%1$s</xliff:g>」<strong></strong>存取您手機中的這項資料"</string>
<string name="summary_app_streaming" product="default" msgid="6105916810614498138">"讓「<xliff:g id="APP_NAME">%1$s</xliff:g>」在「<xliff:g id="DEVICE_NAME">%2$s</xliff:g>」連線時可透過遠端方式存取此手機上安裝的應用程式。"</string>
<string name="summary_app_streaming" product="tablet" msgid="2996373715966272792">"讓「<xliff:g id="APP_NAME">%1$s</xliff:g>」在「<xliff:g id="DEVICE_NAME">%2$s</xliff:g>」連線時可透過遠端方式存取此平板電腦上安裝的應用程式。"</string>
<string name="summary_app_streaming" product="device" msgid="7614171699434639963">"讓「<xliff:g id="APP_NAME">%1$s</xliff:g>」在「<xliff:g id="DEVICE_NAME">%2$s</xliff:g>」連線時可透過遠端方式存取此裝置上安裝的應用程式。"</string>
+ <string name="helper_title_app_streaming" msgid="4151687003439969765">"跨裝置服務"</string>
+ <string name="helper_summary_app_streaming" msgid="5344341720432827388">"此服務是用來在裝置間串流應用程式的內容"</string>
<string name="title_automotive_projection" msgid="3296005598978412847"></string>
<string name="summary_automotive_projection" msgid="8683801274662496164"></string>
<string name="title_computer" msgid="4693714143506569253">"允許「<xliff:g id="APP_NAME">%1$s</xliff:g>」<strong></strong>存取您手機中的這項資料"</string>
<string name="summary_computer" msgid="3798467601598297062"></string>
+ <string name="permission_notification" msgid="693762568127741203">"通知"</string>
+ <string name="permission_notification_summary" msgid="4398672775023193663">"可以讀取所有通知,包括聯絡人、訊息和電話等資訊"</string>
+ <string name="permission_storage" msgid="6831099350839392343">"相片和媒體"</string>
+ <string name="permission_storage_summary" msgid="3918240895519506417"></string>
+ <string name="helper_title_computer" msgid="4671071173916176037">"Google Play 服務"</string>
+ <string name="helper_summary_computer" product="default" msgid="467996390095403648">"此服務可將手機上的相片、媒體及通知分享到其他裝置"</string>
+ <string name="helper_summary_computer" product="tablet" msgid="467996390095403648">"此服務可將手機上的相片、媒體及通知分享到其他裝置"</string>
<string name="profile_name_generic" msgid="6851028682723034988">"裝置"</string>
<string name="summary_generic" msgid="2346762210105903720"></string>
<string name="consent_yes" msgid="8344487259618762872">"允許"</string>
<string name="consent_no" msgid="2640796915611404382">"不允許"</string>
+ <string name="consent_ok" msgid="3662376764371001106">"確定"</string>
<string name="permission_sync_confirmation_title" msgid="667074294393493186">"將應用程式權限轉移至手錶"</string>
<string name="permission_sync_summary" msgid="8873391306499120778">"為簡化手錶的設定程序,在設定過程中安裝到手錶上的應用程式都將沿用手機上的權限。\n\n這些權限可能包括手錶麥克風和位置的存取權。"</string>
</resources>
diff --git a/packages/CompanionDeviceManager/res/values-zh-rTW/strings.xml b/packages/CompanionDeviceManager/res/values-zh-rTW/strings.xml
index eec0424..abefde4 100644
--- a/packages/CompanionDeviceManager/res/values-zh-rTW/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-zh-rTW/strings.xml
@@ -22,18 +22,30 @@
<string name="chooser_title" msgid="2262294130493605839">"選擇要讓「<xliff:g id="APP_NAME">%2$s</xliff:g>」<strong></strong>管理的<xliff:g id="PROFILE_NAME">%1$s</xliff:g>"</string>
<string name="summary_watch" product="default" msgid="7113724443198337683">"「<xliff:g id="APP_NAME">%1$s</xliff:g>」將可存取通知、電話、簡訊、聯絡人和日曆資料。"</string>
<string name="summary_watch" product="tablet" msgid="7113724443198337683">"「<xliff:g id="APP_NAME">%1$s</xliff:g>」將可存取通知、電話、簡訊、聯絡人和日曆資料。"</string>
- <string name="title_app_streaming" msgid="4459136600249308574">"要允許「<xliff:g id="APP_NAME">%1$s</xliff:g>」<strong></strong>串流播放應用程式的內容嗎?"</string>
+ <string name="permission_apps" msgid="6142133265286656158">"應用程式"</string>
+ <string name="permission_apps_summary" msgid="798718816711515431">"串流傳輸手機應用程式內容"</string>
+ <string name="title_app_streaming" msgid="2270331024626446950">"允許「<xliff:g id="APP_NAME">%1$s</xliff:g>」<strong></strong>存取手機中的這項資訊"</string>
<string name="summary_app_streaming" product="default" msgid="6105916810614498138">"允許「<xliff:g id="APP_NAME">%1$s</xliff:g>」<strong></strong>在「<xliff:g id="DEVICE_NAME">%2$s</xliff:g>」<strong></strong>連上網際網路時可從遠端存取該手機上安裝的應用程式。"</string>
<string name="summary_app_streaming" product="tablet" msgid="2996373715966272792">"允許「<xliff:g id="APP_NAME">%1$s</xliff:g>」<strong></strong>在「<xliff:g id="DEVICE_NAME">%2$s</xliff:g>」<strong></strong>連上網際網路時可從遠端存取該平板電腦上安裝的應用程式。"</string>
<string name="summary_app_streaming" product="device" msgid="7614171699434639963">"允許「<xliff:g id="APP_NAME">%1$s</xliff:g>」<strong></strong>在「<xliff:g id="DEVICE_NAME">%2$s</xliff:g>」<strong></strong>連上網際網路時可從遠端存取該裝置上安裝的應用程式。"</string>
+ <string name="helper_title_app_streaming" msgid="4151687003439969765">"跨裝置服務"</string>
+ <string name="helper_summary_app_streaming" msgid="5344341720432827388">"這項服務是用來在裝置間串流傳輸應用程式的內容"</string>
<string name="title_automotive_projection" msgid="3296005598978412847"></string>
<string name="summary_automotive_projection" msgid="8683801274662496164"></string>
<string name="title_computer" msgid="4693714143506569253">"允許「<xliff:g id="APP_NAME">%1$s</xliff:g>」<strong></strong>存取你手機中的這項資訊"</string>
<string name="summary_computer" msgid="3798467601598297062"></string>
+ <string name="permission_notification" msgid="693762568127741203">"通知"</string>
+ <string name="permission_notification_summary" msgid="4398672775023193663">"可以讀取所有通知,包括聯絡人、訊息和電話等資訊"</string>
+ <string name="permission_storage" msgid="6831099350839392343">"相片和媒體"</string>
+ <string name="permission_storage_summary" msgid="3918240895519506417"></string>
+ <string name="helper_title_computer" msgid="4671071173916176037">"Google Play 服務"</string>
+ <string name="helper_summary_computer" product="default" msgid="467996390095403648">"這項服務可將手機上的相片、媒體及通知分享到其他裝置"</string>
+ <string name="helper_summary_computer" product="tablet" msgid="467996390095403648">"這項服務可將手機上的相片、媒體及通知分享到其他裝置"</string>
<string name="profile_name_generic" msgid="6851028682723034988">"裝置"</string>
<string name="summary_generic" msgid="2346762210105903720"></string>
<string name="consent_yes" msgid="8344487259618762872">"允許"</string>
<string name="consent_no" msgid="2640796915611404382">"不允許"</string>
+ <string name="consent_ok" msgid="3662376764371001106">"確定"</string>
<string name="permission_sync_confirmation_title" msgid="667074294393493186">"將應用程式權限轉移到手錶上"</string>
<string name="permission_sync_summary" msgid="8873391306499120778">"為簡化手錶的設定程序,只要是在設定過程中安裝到手錶上的應用程式,都將沿用手機上的權限。\n\n 這些權限可能包括手錶的麥克風和位置資訊存取權。"</string>
</resources>
diff --git a/packages/CompanionDeviceManager/res/values-zu/strings.xml b/packages/CompanionDeviceManager/res/values-zu/strings.xml
index be5a195..1c7cad3 100644
--- a/packages/CompanionDeviceManager/res/values-zu/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-zu/strings.xml
@@ -22,18 +22,30 @@
<string name="chooser_title" msgid="2262294130493605839">"Khetha i-<xliff:g id="PROFILE_NAME">%1$s</xliff:g> ezophathwa yi-<strong><xliff:g id="APP_NAME">%2$s</xliff:g></strong>"</string>
<string name="summary_watch" product="default" msgid="7113724443198337683">"I-<xliff:g id="APP_NAME">%1$s</xliff:g> izovunyelwa ukuxhumana nezaziso zakho futhi ifinyelele izimvume Zefoni yakho, -SMS, Abathintwayo kanye Nekhalenda."</string>
<string name="summary_watch" product="tablet" msgid="7113724443198337683">"I-<xliff:g id="APP_NAME">%1$s</xliff:g> izovunyelwa ukuxhumana nezaziso zakho futhi ifinyelele izimvume Zefoni yakho, -SMS, Abathintwayo kanye Nekhalenda."</string>
- <string name="title_app_streaming" msgid="4459136600249308574">"Vumela <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> ukusakaza ama-applications?"</string>
+ <string name="permission_apps" msgid="6142133265286656158">"Ama-app"</string>
+ <string name="permission_apps_summary" msgid="798718816711515431">"Sakaza ama-app wefoni yakho"</string>
+ <string name="title_app_streaming" msgid="2270331024626446950">"Vumela i-<strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> ifinyelele lolu lwazi kusukela efonini yakho"</string>
<string name="summary_app_streaming" product="default" msgid="6105916810614498138">"Vumela <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> ukunikezela <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong> ngokufinyelela kwerimothi kuma-applications afakiwe kule foni uma ixhunyiwe."</string>
<string name="summary_app_streaming" product="tablet" msgid="2996373715966272792">"Vumela <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> ukunikezela <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong> ngokufinyelela kwerimothi kuma-applications afakiwe kule thebhulethi uma ixhunyiwe."</string>
<string name="summary_app_streaming" product="device" msgid="7614171699434639963">"Vumela <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> ukunikezela <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong> ngokufinyelela kwerimothi kuma-applications afakiwe kule divayisi uma ixhunyiwe."</string>
+ <string name="helper_title_app_streaming" msgid="4151687003439969765">"Amasevisi amadivayisi amaningi"</string>
+ <string name="helper_summary_app_streaming" msgid="5344341720432827388">"Le sevisi isetshenziselwa ukusakaza-bukhoma ama-app phakathi kwamadivayisi akho"</string>
<string name="title_automotive_projection" msgid="3296005598978412847"></string>
<string name="summary_automotive_projection" msgid="8683801274662496164"></string>
<string name="title_computer" msgid="4693714143506569253">"Vumela <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> ukufinyelela lolu lwazi kusuka efonini yakho"</string>
<string name="summary_computer" msgid="3798467601598297062"></string>
+ <string name="permission_notification" msgid="693762568127741203">"Izaziso"</string>
+ <string name="permission_notification_summary" msgid="4398672775023193663">"Ingafunda zonke izaziso, okufaka phakathi ulwazi olufana nomakhontilaki, imiyalezo, nezithombe"</string>
+ <string name="permission_storage" msgid="6831099350839392343">"Izithombe nemidiya"</string>
+ <string name="permission_storage_summary" msgid="3918240895519506417"></string>
+ <string name="helper_title_computer" msgid="4671071173916176037">"Amasevisi we-Google Play"</string>
+ <string name="helper_summary_computer" product="default" msgid="467996390095403648">"Le sevisi yabelana ngezithombe, imidiya, nezaziso kusukela kufoni yakho ukuya kwamanye amadivaysi"</string>
+ <string name="helper_summary_computer" product="tablet" msgid="467996390095403648">"Le sevisi yabelana ngezithombe, imidiya, nezaziso kusukela kufoni yakho ukuya kwamanye amadivaysi"</string>
<string name="profile_name_generic" msgid="6851028682723034988">"idivayisi"</string>
<string name="summary_generic" msgid="2346762210105903720"></string>
<string name="consent_yes" msgid="8344487259618762872">"Vumela"</string>
<string name="consent_no" msgid="2640796915611404382">"Ungavumeli"</string>
+ <string name="consent_ok" msgid="3662376764371001106">"KULUNGILE"</string>
<string name="permission_sync_confirmation_title" msgid="667074294393493186">"Dlulisela izimvume ze-app ewashini lakho"</string>
<string name="permission_sync_summary" msgid="8873391306499120778">"Ukuze wenze kube lula ukusetha iwashi lakho, ama-app afakwe ewashini lakho phakathi nokusetha azosebenzisa izimvume ezifanayo nezefoni yakho.\n\n Lezi zimvume zingabandakanya ukufinyelela kumakrofoni nendawo yewashi lakho."</string>
</resources>
diff --git a/packages/CompanionDeviceManager/res/values/strings.xml b/packages/CompanionDeviceManager/res/values/strings.xml
index 55a1998..67fc6c2 100644
--- a/packages/CompanionDeviceManager/res/values/strings.xml
+++ b/packages/CompanionDeviceManager/res/values/strings.xml
@@ -82,7 +82,7 @@
<string name="permission_notification">Notifications</string>
<!-- Description of notification permission of COMPUTER profile [CHAR LIMIT=NONE] -->
- <string name="permission_notification_summary">Can read all notifications, including information like contracts, messages, and photos</string>
+ <string name="permission_notification_summary">Can read all notifications, including information like contacts, messages, and photos</string>
<!-- Storage permission will be granted of COMPUTER profile [CHAR LIMIT=30] -->
<string name="permission_storage">Photos and media</string>
diff --git a/packages/CompanionDeviceManager/res/values/styles.xml b/packages/CompanionDeviceManager/res/values/styles.xml
index 6eaffd4..a55f30c9 100644
--- a/packages/CompanionDeviceManager/res/values/styles.xml
+++ b/packages/CompanionDeviceManager/res/values/styles.xml
@@ -1,3 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
<!--
~ Copyright (C) 2022 The Android Open Source Project
~
@@ -16,51 +17,86 @@
<resources>
<style name="ContainerLayout">
- <item name="android:padding">18dp</item>
- <item name="android:elevation">16dp</item>
- <item name="android:maxHeight">400dp</item>
- <item name="android:orientation">vertical</item>
- <item name="android:layout_gravity">center</item>
<item name="android:layout_width">match_parent</item>
<item name="android:layout_height">wrap_content</item>
+ <item name="android:orientation">vertical</item>
+ <item name="android:layout_gravity">center</item>
+ <item name="android:minWidth">340dp</item>
<item name="android:background">@drawable/dialog_background</item>
</style>
+ <style name="Description">
+ <item name="android:layout_width">match_parent</item>
+ <item name="android:layout_height">wrap_content</item>
+ <item name="android:orientation">vertical</item>
+ <item name="android:layout_marginTop">18dp</item>
+ <item name="android:layout_marginBottom">18dp</item>
+ <item name="android:layout_marginLeft">24dp</item>
+ <item name="android:layout_marginRight">24dp</item>
+ </style>
+
+ <style name="DescriptionTitle"
+ parent="@*android:style/TextAppearance.Widget.Toolbar.Title">
+ <item name="android:layout_width">match_parent</item>
+ <item name="android:layout_height">wrap_content</item>
+ <item name="android:gravity">center</item>
+ <item name="android:layout_marginLeft">14dp</item>
+ <item name="android:layout_marginRight">14dp</item>
+ <item name="android:textSize">20sp</item>
+ <item name="android:textColor">?android:attr/textColorPrimary</item>
+ </style>
+
+ <style name="DescriptionSummary">
+ <item name="android:layout_width">match_parent</item>
+ <item name="android:layout_height">wrap_content</item>
+ <item name="android:gravity">center</item>
+ <item name="android:layout_marginTop">18dp</item>
+ <item name="android:layout_marginLeft">18dp</item>
+ <item name="android:layout_marginRight">18dp</item>
+ <item name="android:textSize">14sp</item>
+ <item name="android:textColor">?android:attr/textColorSecondary</item>
+ </style>
+
<style name="VendorHelperOkButton"
parent="@android:style/Widget.Material.Button.Borderless.Colored">
<item name="android:layout_width">50dp</item>
- <item name="android:layout_height">35dp</item>
+ <item name="android:layout_height">36dp</item>
<item name="android:layout_marginTop">20dp</item>
<item name="android:textColor">@android:color/system_neutral1_900</item>
<item name="android:background">@drawable/helper_ok_button</item>
</style>
- <style name="NegativeButton"
+ <style name="PositiveButton"
parent="@android:style/Widget.Material.Button.Borderless.Colored">
- <item name="android:layout_width">match_parent</item>
- <item name="android:layout_height">wrap_content</item>
+ <item name="android:layout_width">300dp</item>
+ <item name="android:layout_height">56dp</item>
+ <item name="android:layout_marginLeft">24dp</item>
+ <item name="android:layout_marginRight">24dp</item>
+ <item name="android:layout_marginBottom">2dp</item>
<item name="android:textAllCaps">false</item>
<item name="android:textSize">14sp</item>
<item name="android:textColor">@android:color/system_neutral1_900</item>
- <item name="android:background">@drawable/btn_negative_top</item>
+ <item name="android:background">@drawable/btn_positive_bottom</item>
</style>
- <style name="PositiveButton"
+ <style name="NegativeButton"
parent="@android:style/Widget.Material.Button.Borderless.Colored">
- <item name="android:layout_width">match_parent</item>
- <item name="android:layout_height">wrap_content</item>
+ <item name="android:layout_width">300dp</item>
+ <item name="android:layout_height">56dp</item>
+ <item name="android:layout_marginLeft">24dp</item>
+ <item name="android:layout_marginRight">24dp</item>
+ <item name="android:layout_marginTop">2dp</item>
<item name="android:textAllCaps">false</item>
<item name="android:textSize">14sp</item>
<item name="android:textColor">@android:color/system_neutral1_900</item>
<item name="android:layout_marginTop">4dp</item>
- <item name="android:background">@drawable/btn_positive_bottom</item>
+ <item name="android:background">@drawable/btn_negative_top</item>
</style>
<style name="NegativeButtonMultipleDevices"
parent="@android:style/Widget.Material.Button.Colored">
<item name="android:layout_width">100dp</item>
- <item name="android:layout_height">35dp</item>
- <item name="android:layout_marginTop">20dp</item>
+ <item name="android:layout_height">36dp</item>
<item name="android:textAllCaps">false</item>
<item name="android:background">@drawable/btn_negative_multiple_devices</item>
</style>
diff --git a/packages/CompanionDeviceManager/src/com/android/companiondevicemanager/CompanionDeviceActivity.java b/packages/CompanionDeviceManager/src/com/android/companiondevicemanager/CompanionDeviceActivity.java
index f752b69..0bdf65d 100644
--- a/packages/CompanionDeviceManager/src/com/android/companiondevicemanager/CompanionDeviceActivity.java
+++ b/packages/CompanionDeviceManager/src/com/android/companiondevicemanager/CompanionDeviceActivity.java
@@ -57,6 +57,7 @@
import android.widget.ImageButton;
import android.widget.ImageView;
import android.widget.LinearLayout;
+import android.widget.ProgressBar;
import android.widget.RelativeLayout;
import android.widget.TextView;
@@ -116,14 +117,14 @@
private ImageButton mVendorHeaderButton;
// Progress indicator is only shown while we are looking for the first suitable device for a
- // "regular" (ie. not self-managed) association.
- private View mProgressIndicator;
+ // multiple device association.
+ private ProgressBar mProgressIndicator;
// Present for self-managed association requests and "single-device" regular association
// regular.
private Button mButtonAllow;
private Button mButtonNotAllow;
- // Present for multiple device association requests only.
+ // Present for multiple devices' association requests only.
private Button mButtonNotAllowMultipleDevices;
private LinearLayout mAssociationConfirmationDialog;
@@ -263,6 +264,8 @@
mVendorHeaderButton = findViewById(R.id.vendor_header_button);
mDeviceListRecyclerView = findViewById(R.id.device_list);
+
+ mProgressIndicator = findViewById(R.id.spinner);
mDeviceAdapter = new DeviceListAdapter(this, this::onListItemClick);
mPermissionListRecyclerView = findViewById(R.id.permission_list);
@@ -502,21 +505,25 @@
mSummary.setText(summary);
mProfileIcon.setImageDrawable(profileIcon);
- mDeviceAdapter = new DeviceListAdapter(this, this::onListItemClick);
-
- // TODO: hide the list and show a spinner until a first device matching device is found.
mDeviceListRecyclerView.setAdapter(mDeviceAdapter);
mDeviceListRecyclerView.setLayoutManager(new LinearLayoutManager(this));
- CompanionDeviceDiscoveryService.getScanResult().observe(
- /* lifecycleOwner */ this,
- /* observer */ mDeviceAdapter);
+ CompanionDeviceDiscoveryService.getScanResult().observe(this,
+ deviceFilterPairs -> {
+ // Dismiss the progress bar once there's one device found for multiple devices.
+ if (deviceFilterPairs.size() >= 1) {
+ mProgressIndicator.setVisibility(View.GONE);
+ }
+
+ mDeviceAdapter.setDevices(deviceFilterPairs);
+ });
// "Remove" consent button: users would need to click on the list item.
mButtonAllow.setVisibility(View.GONE);
mButtonNotAllow.setVisibility(View.GONE);
mButtonNotAllowMultipleDevices.setVisibility(View.VISIBLE);
mMultipleDeviceList.setVisibility(View.VISIBLE);
+ mProgressIndicator.setVisibility(View.VISIBLE);
}
private void onListItemClick(int position) {
@@ -564,7 +571,7 @@
CompanionVendorHelperDialogFragment.newInstance(mRequest.getPackageName(),
mRequest.getUserId(), mRequest.getDeviceProfile());
- mAssociationConfirmationDialog.setVisibility(View.GONE);
+ mAssociationConfirmationDialog.setVisibility(View.INVISIBLE);
fragmentDialog.show(fragmentManager, /* Tag */ FRAGMENT_DIALOG_TAG);
}
diff --git a/packages/CompanionDeviceManager/src/com/android/companiondevicemanager/CompanionDeviceDiscoveryService.java b/packages/CompanionDeviceManager/src/com/android/companiondevicemanager/CompanionDeviceDiscoveryService.java
index 5f07fcf..e8a1a5c 100644
--- a/packages/CompanionDeviceManager/src/com/android/companiondevicemanager/CompanionDeviceDiscoveryService.java
+++ b/packages/CompanionDeviceManager/src/com/android/companiondevicemanager/CompanionDeviceDiscoveryService.java
@@ -150,6 +150,8 @@
mBtAdapter = mBtManager.getAdapter();
mBleScanner = mBtAdapter.getBluetoothLeScanner();
mWifiManager = getSystemService(WifiManager.class);
+
+ sScanResultsLiveData.setValue(Collections.emptyList());
}
@Override
@@ -186,7 +188,6 @@
mStopAfterFirstMatch = request.isSingleDevice();
mDiscoveryStarted = true;
sStateLiveData.setValue(DiscoveryState.DISCOVERY_IN_PROGRESS);
- sScanResultsLiveData.setValue(Collections.emptyList());
final List<DeviceFilter<?>> allFilters = request.getDeviceFilters();
final List<BluetoothDeviceFilter> btFilters =
diff --git a/packages/CompanionDeviceManager/src/com/android/companiondevicemanager/DeviceListAdapter.java b/packages/CompanionDeviceManager/src/com/android/companiondevicemanager/DeviceListAdapter.java
index 8babd3a..328c67e 100644
--- a/packages/CompanionDeviceManager/src/com/android/companiondevicemanager/DeviceListAdapter.java
+++ b/packages/CompanionDeviceManager/src/com/android/companiondevicemanager/DeviceListAdapter.java
@@ -25,15 +25,13 @@
import android.widget.ImageView;
import android.widget.TextView;
-import androidx.lifecycle.Observer;
import androidx.recyclerview.widget.RecyclerView;
import java.util.List;
/**
* Adapter for the list of "found" devices.
*/
-class DeviceListAdapter extends RecyclerView.Adapter<DeviceListAdapter.ViewHolder> implements
- Observer<List<DeviceFilterPair<?>>> {
+class DeviceListAdapter extends RecyclerView.Adapter<DeviceListAdapter.ViewHolder> {
public int mSelectedPosition = RecyclerView.NO_POSITION;
private final Context mContext;
@@ -96,9 +94,8 @@
mSelectedPosition = position;
}
- @Override
- public void onChanged(List<DeviceFilterPair<?>> deviceFilterPairs) {
- mDevices = deviceFilterPairs;
+ void setDevices(List<DeviceFilterPair<?>> devices) {
+ mDevices = devices;
notifyDataSetChanged();
}
diff --git a/packages/ConnectivityT/framework-t/Android.bp b/packages/ConnectivityT/framework-t/Android.bp
index 217a1f67c3..bc27852 100644
--- a/packages/ConnectivityT/framework-t/Android.bp
+++ b/packages/ConnectivityT/framework-t/Android.bp
@@ -131,8 +131,8 @@
"src/android/net/EthernetNetworkUpdateRequest.java",
"src/android/net/EthernetNetworkUpdateRequest.aidl",
"src/android/net/IEthernetManager.aidl",
- "src/android/net/IEthernetNetworkManagementListener.aidl",
"src/android/net/IEthernetServiceListener.aidl",
+ "src/android/net/INetworkInterfaceOutcomeReceiver.aidl",
"src/android/net/ITetheredInterfaceCallback.aidl",
],
path: "src",
diff --git a/packages/ConnectivityT/framework-t/src/android/app/usage/NetworkStats.java b/packages/ConnectivityT/framework-t/src/android/app/usage/NetworkStats.java
index 2b6570a..74fe4bd 100644
--- a/packages/ConnectivityT/framework-t/src/android/app/usage/NetworkStats.java
+++ b/packages/ConnectivityT/framework-t/src/android/app/usage/NetworkStats.java
@@ -17,6 +17,7 @@
package android.app.usage;
import android.annotation.IntDef;
+import android.annotation.Nullable;
import android.content.Context;
import android.net.INetworkStatsService;
import android.net.INetworkStatsSession;
@@ -474,10 +475,11 @@
/**
* Fills the recycled bucket with data of the next bin in the enumeration.
- * @param bucketOut Bucket to be filled with data.
+ * @param bucketOut Bucket to be filled with data. If null, the method does
+ * nothing and returning false.
* @return true if successfully filled the bucket, false otherwise.
*/
- public boolean getNextBucket(Bucket bucketOut) {
+ public boolean getNextBucket(@Nullable Bucket bucketOut) {
if (mSummary != null) {
return getNextSummaryBucket(bucketOut);
} else {
@@ -651,7 +653,7 @@
* @param bucketOut Next item will be set here.
* @return true if a next item could be set.
*/
- private boolean getNextSummaryBucket(Bucket bucketOut) {
+ private boolean getNextSummaryBucket(@Nullable Bucket bucketOut) {
if (bucketOut != null && mEnumerationIndex < mSummary.size()) {
mRecycledSummaryEntry = mSummary.getValues(mEnumerationIndex++, mRecycledSummaryEntry);
fillBucketFromSummaryEntry(bucketOut);
@@ -678,7 +680,7 @@
* @param bucketOut Next item will be set here.
* @return true if a next item could be set.
*/
- private boolean getNextHistoryBucket(Bucket bucketOut) {
+ private boolean getNextHistoryBucket(@Nullable Bucket bucketOut) {
if (bucketOut != null && mHistory != null) {
if (mEnumerationIndex < mHistory.size()) {
mRecycledHistoryEntry = mHistory.getValues(mEnumerationIndex++,
diff --git a/packages/ConnectivityT/framework-t/src/android/app/usage/NetworkStatsManager.java b/packages/ConnectivityT/framework-t/src/android/app/usage/NetworkStatsManager.java
index ca080ce..f41475b 100644
--- a/packages/ConnectivityT/framework-t/src/android/app/usage/NetworkStatsManager.java
+++ b/packages/ConnectivityT/framework-t/src/android/app/usage/NetworkStatsManager.java
@@ -290,7 +290,7 @@
* statistics collection.
*/
@WorkerThread
- public Bucket querySummaryForDevice(int networkType, String subscriberId,
+ public Bucket querySummaryForDevice(int networkType, @Nullable String subscriberId,
long startTime, long endTime) throws SecurityException, RemoteException {
NetworkTemplate template;
try {
@@ -335,8 +335,8 @@
* statistics collection.
*/
@WorkerThread
- public Bucket querySummaryForUser(int networkType, String subscriberId, long startTime,
- long endTime) throws SecurityException, RemoteException {
+ public Bucket querySummaryForUser(int networkType, @Nullable String subscriberId,
+ long startTime, long endTime) throws SecurityException, RemoteException {
NetworkTemplate template;
try {
template = createTemplate(networkType, subscriberId);
@@ -384,7 +384,7 @@
* statistics collection.
*/
@WorkerThread
- public NetworkStats querySummary(int networkType, String subscriberId, long startTime,
+ public NetworkStats querySummary(int networkType, @Nullable String subscriberId, long startTime,
long endTime) throws SecurityException, RemoteException {
NetworkTemplate template;
try {
@@ -508,15 +508,17 @@
*
* @see #queryDetailsForUidTagState(int, String, long, long, int, int, int)
*/
+ @NonNull
@WorkerThread
- public NetworkStats queryDetailsForUid(int networkType, String subscriberId,
+ public NetworkStats queryDetailsForUid(int networkType, @Nullable String subscriberId,
long startTime, long endTime, int uid) throws SecurityException {
return queryDetailsForUidTagState(networkType, subscriberId, startTime, endTime, uid,
NetworkStats.Bucket.TAG_NONE, NetworkStats.Bucket.STATE_ALL);
}
/** @hide */
- public NetworkStats queryDetailsForUid(NetworkTemplate template,
+ @NonNull
+ public NetworkStats queryDetailsForUid(@NonNull NetworkTemplate template,
long startTime, long endTime, int uid) throws SecurityException {
return queryDetailsForUidTagState(template, startTime, endTime, uid,
NetworkStats.Bucket.TAG_NONE, NetworkStats.Bucket.STATE_ALL);
@@ -524,23 +526,59 @@
/**
* Query network usage statistics details for a given uid and tag.
+ *
+ * This may take a long time, and apps should avoid calling this on their main thread.
+ * Only usable for uids belonging to calling user. Result is not aggregated over time.
+ * This means buckets' start and end timestamps are going to be between 'startTime' and
+ * 'endTime' parameters. The uid is going to be the same as the 'uid' parameter, the tag
+ * the same as the 'tag' parameter, and the state the same as the 'state' parameter.
+ * defaultNetwork is going to be {@link NetworkStats.Bucket#DEFAULT_NETWORK_ALL},
+ * metered is going to be {@link NetworkStats.Bucket#METERED_ALL}, and
+ * roaming is going to be {@link NetworkStats.Bucket#ROAMING_ALL}.
+ * <p>Only includes buckets that atomically occur in the inclusive time range. Doesn't
+ * interpolate across partial buckets. Since bucket length is in the order of hours, this
+ * method cannot be used to measure data usage on a fine grained time scale.
* This may take a long time, and apps should avoid calling this on their main thread.
*
- * @see #queryDetailsForUidTagState(int, String, long, long, int, int, int)
+ * @param networkType As defined in {@link ConnectivityManager}, e.g.
+ * {@link ConnectivityManager#TYPE_MOBILE}, {@link ConnectivityManager#TYPE_WIFI}
+ * etc.
+ * @param subscriberId If applicable, the subscriber id of the network interface.
+ * <p>Starting with API level 29, the {@code subscriberId} is guarded by
+ * additional restrictions. Calling apps that do not meet the new
+ * requirements to access the {@code subscriberId} can provide a {@code
+ * null} value when querying for the mobile network type to receive usage
+ * for all mobile networks. For additional details see {@link
+ * TelephonyManager#getSubscriberId()}.
+ * <p>Starting with API level 31, calling apps can provide a
+ * {@code subscriberId} with wifi network type to receive usage for
+ * wifi networks which is under the given subscription if applicable.
+ * Otherwise, pass {@code null} when querying all wifi networks.
+ * @param startTime Start of period. Defined in terms of "Unix time", see
+ * {@link java.lang.System#currentTimeMillis}.
+ * @param endTime End of period. Defined in terms of "Unix time", see
+ * {@link java.lang.System#currentTimeMillis}.
+ * @param uid UID of app
+ * @param tag TAG of interest. Use {@link NetworkStats.Bucket#TAG_NONE} for aggregated data
+ * across all the tags.
+ * @return Statistics which is described above.
+ * @throws SecurityException if permissions are insufficient to read network statistics.
*/
+ @NonNull
@WorkerThread
- public NetworkStats queryDetailsForUidTag(int networkType, String subscriberId,
+ public NetworkStats queryDetailsForUidTag(int networkType, @Nullable String subscriberId,
long startTime, long endTime, int uid, int tag) throws SecurityException {
return queryDetailsForUidTagState(networkType, subscriberId, startTime, endTime, uid,
tag, NetworkStats.Bucket.STATE_ALL);
}
/**
- * Query network usage statistics details for a given uid, tag, and state. Only usable for uids
- * belonging to calling user. Result is not aggregated over time. This means buckets' start and
- * end timestamps are going to be between 'startTime' and 'endTime' parameters. The uid is going
- * to be the same as the 'uid' parameter, the tag the same as the 'tag' parameter, and the state
- * the same as the 'state' parameter.
+ * Query network usage statistics details for a given uid, tag, and state.
+ *
+ * Only usable for uids belonging to calling user. Result is not aggregated over time.
+ * This means buckets' start and end timestamps are going to be between 'startTime' and
+ * 'endTime' parameters. The uid is going to be the same as the 'uid' parameter, the tag
+ * the same as the 'tag' parameter, and the state the same as the 'state' parameter.
* defaultNetwork is going to be {@link NetworkStats.Bucket#DEFAULT_NETWORK_ALL},
* metered is going to be {@link NetworkStats.Bucket#METERED_ALL}, and
* roaming is going to be {@link NetworkStats.Bucket#ROAMING_ALL}.
@@ -572,11 +610,12 @@
* across all the tags.
* @param state state of interest. Use {@link NetworkStats.Bucket#STATE_ALL} to aggregate
* traffic from all states.
- * @return Statistics object or null if an error happened during statistics collection.
+ * @return Statistics which is described above.
* @throws SecurityException if permissions are insufficient to read network statistics.
*/
+ @NonNull
@WorkerThread
- public NetworkStats queryDetailsForUidTagState(int networkType, String subscriberId,
+ public NetworkStats queryDetailsForUidTagState(int networkType, @Nullable String subscriberId,
long startTime, long endTime, int uid, int tag, int state) throws SecurityException {
NetworkTemplate template;
template = createTemplate(networkType, subscriberId);
@@ -669,7 +708,7 @@
* statistics collection.
*/
@WorkerThread
- public NetworkStats queryDetails(int networkType, String subscriberId, long startTime,
+ public NetworkStats queryDetails(int networkType, @Nullable String subscriberId, long startTime,
long endTime) throws SecurityException, RemoteException {
NetworkTemplate template;
try {
@@ -698,7 +737,7 @@
*
* @hide
*/
- @SystemApi
+ @SystemApi(client = MODULE_LIBRARIES)
@RequiresPermission(anyOf = {
NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK,
android.Manifest.permission.NETWORK_STACK})
@@ -724,7 +763,7 @@
*
* @hide
*/
- @SystemApi
+ @SystemApi(client = MODULE_LIBRARIES)
@RequiresPermission(anyOf = {
NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK,
android.Manifest.permission.NETWORK_STACK})
@@ -785,10 +824,28 @@
/**
* Registers to receive notifications about data usage on specified networks.
*
- * @see #registerUsageCallback(int, String, long, UsageCallback, Handler)
+ * <p>The callbacks will continue to be called as long as the process is live or
+ * {@link #unregisterUsageCallback} is called.
+ *
+ * @param networkType Type of network to monitor. Either
+ {@link ConnectivityManager#TYPE_MOBILE} or {@link ConnectivityManager#TYPE_WIFI}.
+ * @param subscriberId If applicable, the subscriber id of the network interface.
+ * <p>Starting with API level 29, the {@code subscriberId} is guarded by
+ * additional restrictions. Calling apps that do not meet the new
+ * requirements to access the {@code subscriberId} can provide a {@code
+ * null} value when registering for the mobile network type to receive
+ * notifications for all mobile networks. For additional details see {@link
+ * TelephonyManager#getSubscriberId()}.
+ * <p>Starting with API level 31, calling apps can provide a
+ * {@code subscriberId} with wifi network type to receive usage for
+ * wifi networks which is under the given subscription if applicable.
+ * Otherwise, pass {@code null} when querying all wifi networks.
+ * @param thresholdBytes Threshold in bytes to be notified on.
+ * @param callback The {@link UsageCallback} that the system will call when data usage
+ * has exceeded the specified threshold.
*/
- public void registerUsageCallback(int networkType, String subscriberId, long thresholdBytes,
- UsageCallback callback) {
+ public void registerUsageCallback(int networkType, @Nullable String subscriberId,
+ long thresholdBytes, @NonNull UsageCallback callback) {
registerUsageCallback(networkType, subscriberId, thresholdBytes, callback,
null /* handler */);
}
@@ -818,8 +875,8 @@
* @param handler to dispatch callback events through, otherwise if {@code null} it uses
* the calling thread.
*/
- public void registerUsageCallback(int networkType, String subscriberId, long thresholdBytes,
- UsageCallback callback, @Nullable Handler handler) {
+ public void registerUsageCallback(int networkType, @Nullable String subscriberId,
+ long thresholdBytes, @NonNull UsageCallback callback, @Nullable Handler handler) {
NetworkTemplate template = createTemplate(networkType, subscriberId);
if (DBG) {
Log.d(TAG, "registerUsageCallback called with: {"
@@ -839,7 +896,7 @@
*
* @param callback The {@link UsageCallback} used when registering.
*/
- public void unregisterUsageCallback(UsageCallback callback) {
+ public void unregisterUsageCallback(@NonNull UsageCallback callback) {
if (callback == null || callback.request == null
|| callback.request.requestId == DataUsageRequest.REQUEST_ID_UNSET) {
throw new IllegalArgumentException("Invalid UsageCallback");
@@ -880,7 +937,7 @@
/**
* Called when data usage has reached the given threshold.
*/
- public abstract void onThresholdReached(int networkType, String subscriberId);
+ public abstract void onThresholdReached(int networkType, @Nullable String subscriberId);
/**
* @hide used for internal bookkeeping
@@ -924,7 +981,7 @@
@RequiresPermission(anyOf = {
android.Manifest.permission.NETWORK_STATS_PROVIDER,
NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK})
- @NonNull public void registerNetworkStatsProvider(
+ public void registerNetworkStatsProvider(
@NonNull String tag,
@NonNull NetworkStatsProvider provider) {
try {
@@ -950,7 +1007,7 @@
@RequiresPermission(anyOf = {
android.Manifest.permission.NETWORK_STATS_PROVIDER,
NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK})
- @NonNull public void unregisterNetworkStatsProvider(@NonNull NetworkStatsProvider provider) {
+ public void unregisterNetworkStatsProvider(@NonNull NetworkStatsProvider provider) {
try {
provider.getProviderCallbackBinderOrThrow().unregister();
} catch (RemoteException e) {
@@ -958,7 +1015,7 @@
}
}
- private static NetworkTemplate createTemplate(int networkType, String subscriberId) {
+ private static NetworkTemplate createTemplate(int networkType, @Nullable String subscriberId) {
final NetworkTemplate template;
switch (networkType) {
case ConnectivityManager.TYPE_MOBILE:
@@ -1061,9 +1118,9 @@
@RequiresPermission(anyOf = {
NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK,
android.Manifest.permission.NETWORK_STACK})
- public void setUidForeground(int uid, boolean uidForeground) {
+ public void noteUidForeground(int uid, boolean uidForeground) {
try {
- mService.setUidForeground(uid, uidForeground);
+ mService.noteUidForeground(uid, uidForeground);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
diff --git a/packages/ConnectivityT/framework-t/src/android/net/EthernetManager.java b/packages/ConnectivityT/framework-t/src/android/net/EthernetManager.java
index 793f28d..e02ea89 100644
--- a/packages/ConnectivityT/framework-t/src/android/net/EthernetManager.java
+++ b/packages/ConnectivityT/framework-t/src/android/net/EthernetManager.java
@@ -30,6 +30,7 @@
import android.content.Context;
import android.content.pm.PackageManager;
import android.os.Build;
+import android.os.OutcomeReceiver;
import android.os.RemoteException;
import com.android.internal.annotations.GuardedBy;
@@ -38,9 +39,10 @@
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.util.ArrayList;
+import java.util.List;
import java.util.Objects;
import java.util.concurrent.Executor;
-import java.util.function.BiConsumer;
+import java.util.function.IntConsumer;
/**
* A class that manages and configures Ethernet interfaces.
@@ -53,15 +55,31 @@
private static final String TAG = "EthernetManager";
private final IEthernetManager mService;
- @GuardedBy("mListeners")
- private final ArrayList<ListenerInfo> mListeners = new ArrayList<>();
+ @GuardedBy("mListenerLock")
+ private final ArrayList<ListenerInfo<InterfaceStateListener>> mIfaceListeners =
+ new ArrayList<>();
+ @GuardedBy("mListenerLock")
+ private final ArrayList<ListenerInfo<IntConsumer>> mEthernetStateListeners =
+ new ArrayList<>();
+ final Object mListenerLock = new Object();
private final IEthernetServiceListener.Stub mServiceListener =
new IEthernetServiceListener.Stub() {
@Override
+ public void onEthernetStateChanged(int state) {
+ synchronized (mListenerLock) {
+ for (ListenerInfo<IntConsumer> li : mEthernetStateListeners) {
+ li.executor.execute(() -> {
+ li.listener.accept(state);
+ });
+ }
+ }
+ }
+
+ @Override
public void onInterfaceStateChanged(String iface, int state, int role,
IpConfiguration configuration) {
- synchronized (mListeners) {
- for (ListenerInfo li : mListeners) {
+ synchronized (mListenerLock) {
+ for (ListenerInfo<InterfaceStateListener> li : mIfaceListeners) {
li.executor.execute(() ->
li.listener.onInterfaceStateChanged(iface, state, role,
configuration));
@@ -70,13 +88,29 @@
}
};
- private static class ListenerInfo {
+ /**
+ * Indicates that Ethernet is disabled.
+ *
+ * @hide
+ */
+ @SystemApi(client = MODULE_LIBRARIES)
+ public static final int ETHERNET_STATE_DISABLED = 0;
+
+ /**
+ * Indicates that Ethernet is enabled.
+ *
+ * @hide
+ */
+ @SystemApi(client = MODULE_LIBRARIES)
+ public static final int ETHERNET_STATE_ENABLED = 1;
+
+ private static class ListenerInfo<T> {
@NonNull
public final Executor executor;
@NonNull
- public final InterfaceStateListener listener;
+ public final T listener;
- private ListenerInfo(@NonNull Executor executor, @NonNull InterfaceStateListener listener) {
+ private ListenerInfo(@NonNull Executor executor, @NonNull T listener) {
this.executor = executor;
this.listener = listener;
}
@@ -289,18 +323,24 @@
if (listener == null || executor == null) {
throw new NullPointerException("listener and executor must not be null");
}
- synchronized (mListeners) {
- mListeners.add(new ListenerInfo(executor, listener));
- if (mListeners.size() == 1) {
- try {
- mService.addListener(mServiceListener);
- } catch (RemoteException e) {
- throw e.rethrowFromSystemServer();
- }
- }
+ synchronized (mListenerLock) {
+ maybeAddServiceListener();
+ mIfaceListeners.add(new ListenerInfo<InterfaceStateListener>(executor, listener));
}
}
+ @GuardedBy("mListenerLock")
+ private void maybeAddServiceListener() {
+ if (!mIfaceListeners.isEmpty() || !mEthernetStateListeners.isEmpty()) return;
+
+ try {
+ mService.addListener(mServiceListener);
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+
+ }
+
/**
* Returns an array of available Ethernet interface names.
* @hide
@@ -323,15 +363,20 @@
@SystemApi(client = MODULE_LIBRARIES)
public void removeInterfaceStateListener(@NonNull InterfaceStateListener listener) {
Objects.requireNonNull(listener);
- synchronized (mListeners) {
- mListeners.removeIf(l -> l.listener == listener);
- if (mListeners.isEmpty()) {
- try {
- mService.removeListener(mServiceListener);
- } catch (RemoteException e) {
- throw e.rethrowFromSystemServer();
- }
- }
+ synchronized (mListenerLock) {
+ mIfaceListeners.removeIf(l -> l.listener == listener);
+ maybeRemoveServiceListener();
+ }
+ }
+
+ @GuardedBy("mListenerLock")
+ private void maybeRemoveServiceListener() {
+ if (!mIfaceListeners.isEmpty() || !mEthernetStateListeners.isEmpty()) return;
+
+ try {
+ mService.removeListener(mServiceListener);
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
}
}
@@ -443,41 +488,45 @@
return new TetheredInterfaceRequest(mService, cbInternal);
}
- private static final class InternalNetworkManagementListener
- extends IEthernetNetworkManagementListener.Stub {
+ private static final class NetworkInterfaceOutcomeReceiver
+ extends INetworkInterfaceOutcomeReceiver.Stub {
@NonNull
private final Executor mExecutor;
@NonNull
- private final BiConsumer<Network, EthernetNetworkManagementException> mListener;
+ private final OutcomeReceiver<String, EthernetNetworkManagementException> mCallback;
- InternalNetworkManagementListener(
+ NetworkInterfaceOutcomeReceiver(
@NonNull final Executor executor,
- @NonNull final BiConsumer<Network, EthernetNetworkManagementException> listener) {
+ @NonNull final OutcomeReceiver<String, EthernetNetworkManagementException>
+ callback) {
Objects.requireNonNull(executor, "Pass a non-null executor");
- Objects.requireNonNull(listener, "Pass a non-null listener");
+ Objects.requireNonNull(callback, "Pass a non-null callback");
mExecutor = executor;
- mListener = listener;
+ mCallback = callback;
}
@Override
- public void onComplete(
- @Nullable final Network network,
- @Nullable final EthernetNetworkManagementException e) {
- mExecutor.execute(() -> mListener.accept(network, e));
+ public void onResult(@NonNull String iface) {
+ mExecutor.execute(() -> mCallback.onResult(iface));
+ }
+
+ @Override
+ public void onError(@NonNull EthernetNetworkManagementException e) {
+ mExecutor.execute(() -> mCallback.onError(e));
}
}
- private InternalNetworkManagementListener getInternalNetworkManagementListener(
+ private NetworkInterfaceOutcomeReceiver makeNetworkInterfaceOutcomeReceiver(
@Nullable final Executor executor,
- @Nullable final BiConsumer<Network, EthernetNetworkManagementException> listener) {
- if (null != listener) {
- Objects.requireNonNull(executor, "Pass a non-null executor, or a null listener");
+ @Nullable final OutcomeReceiver<String, EthernetNetworkManagementException> callback) {
+ if (null != callback) {
+ Objects.requireNonNull(executor, "Pass a non-null executor, or a null callback");
}
- final InternalNetworkManagementListener proxy;
- if (null == listener) {
+ final NetworkInterfaceOutcomeReceiver proxy;
+ if (null == callback) {
proxy = null;
} else {
- proxy = new InternalNetworkManagementListener(executor, listener);
+ proxy = new NetworkInterfaceOutcomeReceiver(executor, callback);
}
return proxy;
}
@@ -492,14 +541,17 @@
* Similarly, use {@link NetworkCapabilities.Builder} to build a {@code NetworkCapabilities}
* object for this network to put inside the {@code request}.
*
- * If non-null, the listener will be called exactly once after this is called, unless
- * a synchronous exception was thrown.
+ * This function accepts an {@link OutcomeReceiver} that is called once the operation has
+ * finished execution.
*
* @param iface the name of the interface to act upon.
* @param request the {@link EthernetNetworkUpdateRequest} used to set an ethernet network's
* {@link StaticIpConfiguration} and {@link NetworkCapabilities} values.
- * @param executor an {@link Executor} to execute the listener on. Optional if listener is null.
- * @param listener an optional {@link BiConsumer} to listen for completion of the operation.
+ * @param executor an {@link Executor} to execute the callback on. Optional if callback is null.
+ * @param callback an optional {@link OutcomeReceiver} to listen for completion of the
+ * operation. On success, {@link OutcomeReceiver#onResult} is called with the
+ * interface name. On error, {@link OutcomeReceiver#onError} is called with more
+ * information about the error.
* @throws SecurityException if the process doesn't hold
* {@link android.Manifest.permission.MANAGE_ETHERNET_NETWORKS}.
* @throws UnsupportedOperationException if called on a non-automotive device or on an
@@ -515,11 +567,11 @@
@NonNull String iface,
@NonNull EthernetNetworkUpdateRequest request,
@Nullable @CallbackExecutor Executor executor,
- @Nullable BiConsumer<Network, EthernetNetworkManagementException> listener) {
+ @Nullable OutcomeReceiver<String, EthernetNetworkManagementException> callback) {
Objects.requireNonNull(iface, "iface must be non-null");
Objects.requireNonNull(request, "request must be non-null");
- final InternalNetworkManagementListener proxy = getInternalNetworkManagementListener(
- executor, listener);
+ final NetworkInterfaceOutcomeReceiver proxy = makeNetworkInterfaceOutcomeReceiver(
+ executor, callback);
try {
mService.updateConfiguration(iface, request, proxy);
} catch (RemoteException e) {
@@ -528,20 +580,20 @@
}
/**
- * Set an ethernet network's link state up.
+ * Enable a network interface.
*
- * When the link is successfully turned up, the listener will be called with the resulting
- * network. If any error or unexpected condition happens while the system tries to turn the
- * interface up, the listener will be called with an appropriate exception.
- * The listener is guaranteed to be called exactly once for each call to this method, but this
- * may take an unbounded amount of time depending on the actual network conditions.
+ * Enables a previously disabled network interface.
+ * This function accepts an {@link OutcomeReceiver} that is called once the operation has
+ * finished execution.
*
- * @param iface the name of the interface to act upon.
- * @param executor an {@link Executor} to execute the listener on. Optional if listener is null.
- * @param listener an optional {@link BiConsumer} to listen for completion of the operation.
+ * @param iface the name of the interface to enable.
+ * @param executor an {@link Executor} to execute the callback on. Optional if callback is null.
+ * @param callback an optional {@link OutcomeReceiver} to listen for completion of the
+ * operation. On success, {@link OutcomeReceiver#onResult} is called with the
+ * interface name. On error, {@link OutcomeReceiver#onError} is called with more
+ * information about the error.
* @throws SecurityException if the process doesn't hold
* {@link android.Manifest.permission.MANAGE_ETHERNET_NETWORKS}.
- * @throws UnsupportedOperationException if called on a non-automotive device.
* @hide
*/
@SystemApi
@@ -550,13 +602,13 @@
android.Manifest.permission.NETWORK_STACK,
android.Manifest.permission.MANAGE_ETHERNET_NETWORKS})
@RequiresFeature(PackageManager.FEATURE_AUTOMOTIVE)
- public void connectNetwork(
+ public void enableInterface(
@NonNull String iface,
@Nullable @CallbackExecutor Executor executor,
- @Nullable BiConsumer<Network, EthernetNetworkManagementException> listener) {
+ @Nullable OutcomeReceiver<String, EthernetNetworkManagementException> callback) {
Objects.requireNonNull(iface, "iface must be non-null");
- final InternalNetworkManagementListener proxy = getInternalNetworkManagementListener(
- executor, listener);
+ final NetworkInterfaceOutcomeReceiver proxy = makeNetworkInterfaceOutcomeReceiver(
+ executor, callback);
try {
mService.connectNetwork(iface, proxy);
} catch (RemoteException e) {
@@ -565,19 +617,21 @@
}
/**
- * Set an ethernet network's link state down.
+ * Disable a network interface.
*
- * When the link is successfully turned down, the listener will be called with the network that
- * was torn down, if any. If any error or unexpected condition happens while the system tries to
- * turn the interface down, the listener will be called with an appropriate exception.
- * The listener is guaranteed to be called exactly once for each call to this method.
+ * Disables the use of a network interface to fulfill network requests. If the interface
+ * currently serves a request, the network will be torn down.
+ * This function accepts an {@link OutcomeReceiver} that is called once the operation has
+ * finished execution.
*
- * @param iface the name of the interface to act upon.
- * @param executor an {@link Executor} to execute the listener on. Optional if listener is null.
- * @param listener an optional {@link BiConsumer} to listen for completion of the operation.
+ * @param iface the name of the interface to disable.
+ * @param executor an {@link Executor} to execute the callback on. Optional if callback is null.
+ * @param callback an optional {@link OutcomeReceiver} to listen for completion of the
+ * operation. On success, {@link OutcomeReceiver#onResult} is called with the
+ * interface name. On error, {@link OutcomeReceiver#onError} is called with more
+ * information about the error.
* @throws SecurityException if the process doesn't hold
* {@link android.Manifest.permission.MANAGE_ETHERNET_NETWORKS}.
- * @throws UnsupportedOperationException if called on a non-automotive device.
* @hide
*/
@SystemApi
@@ -586,17 +640,90 @@
android.Manifest.permission.NETWORK_STACK,
android.Manifest.permission.MANAGE_ETHERNET_NETWORKS})
@RequiresFeature(PackageManager.FEATURE_AUTOMOTIVE)
- public void disconnectNetwork(
+ public void disableInterface(
@NonNull String iface,
@Nullable @CallbackExecutor Executor executor,
- @Nullable BiConsumer<Network, EthernetNetworkManagementException> listener) {
+ @Nullable OutcomeReceiver<String, EthernetNetworkManagementException> callback) {
Objects.requireNonNull(iface, "iface must be non-null");
- final InternalNetworkManagementListener proxy = getInternalNetworkManagementListener(
- executor, listener);
+ final NetworkInterfaceOutcomeReceiver proxy = makeNetworkInterfaceOutcomeReceiver(
+ executor, callback);
try {
mService.disconnectNetwork(iface, proxy);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
}
+
+ /**
+ * Change ethernet setting.
+ *
+ * @param enabled enable or disable ethernet settings.
+ *
+ * @hide
+ */
+ @RequiresPermission(anyOf = {
+ NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK,
+ android.Manifest.permission.NETWORK_STACK,
+ android.Manifest.permission.NETWORK_SETTINGS})
+ @SystemApi(client = MODULE_LIBRARIES)
+ public void setEthernetEnabled(boolean enabled) {
+ try {
+ mService.setEthernetEnabled(enabled);
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+
+ /**
+ * Listen to changes in the state of ethernet.
+ *
+ * @param executor to run callbacks on.
+ * @param listener to listen ethernet state changed.
+ *
+ * @hide
+ */
+ @RequiresPermission(android.Manifest.permission.ACCESS_NETWORK_STATE)
+ @SystemApi(client = MODULE_LIBRARIES)
+ public void addEthernetStateListener(@NonNull Executor executor,
+ @NonNull IntConsumer listener) {
+ Objects.requireNonNull(executor);
+ Objects.requireNonNull(listener);
+ synchronized (mListenerLock) {
+ maybeAddServiceListener();
+ mEthernetStateListeners.add(new ListenerInfo<IntConsumer>(executor, listener));
+ }
+ }
+
+ /**
+ * Removes a listener.
+ *
+ * @param listener to listen ethernet state changed.
+ *
+ * @hide
+ */
+ @RequiresPermission(android.Manifest.permission.ACCESS_NETWORK_STATE)
+ @SystemApi(client = MODULE_LIBRARIES)
+ public void removeEthernetStateListener(@NonNull IntConsumer listener) {
+ Objects.requireNonNull(listener);
+ synchronized (mListenerLock) {
+ mEthernetStateListeners.removeIf(l -> l.listener == listener);
+ maybeRemoveServiceListener();
+ }
+ }
+
+ /**
+ * Returns an array of existing Ethernet interface names regardless whether the interface
+ * is available or not currently.
+ * @hide
+ */
+ @RequiresPermission(android.Manifest.permission.ACCESS_NETWORK_STATE)
+ @SystemApi(client = MODULE_LIBRARIES)
+ @NonNull
+ public List<String> getInterfaceList() {
+ try {
+ return mService.getInterfaceList();
+ } catch (RemoteException e) {
+ throw e.rethrowAsRuntimeException();
+ }
+ }
}
diff --git a/packages/ConnectivityT/framework-t/src/android/net/EthernetNetworkUpdateRequest.java b/packages/ConnectivityT/framework-t/src/android/net/EthernetNetworkUpdateRequest.java
index 43f4c40..1691942 100644
--- a/packages/ConnectivityT/framework-t/src/android/net/EthernetNetworkUpdateRequest.java
+++ b/packages/ConnectivityT/framework-t/src/android/net/EthernetNetworkUpdateRequest.java
@@ -33,17 +33,20 @@
*/
@SystemApi
public final class EthernetNetworkUpdateRequest implements Parcelable {
- @NonNull
+ @Nullable
private final IpConfiguration mIpConfig;
@Nullable
private final NetworkCapabilities mNetworkCapabilities;
/**
- * @return the new {@link IpConfiguration}.
+ * Setting the {@link IpConfiguration} is optional in {@link EthernetNetworkUpdateRequest}.
+ * When set to null, the existing IpConfiguration is not updated.
+ *
+ * @return the new {@link IpConfiguration} or null.
*/
- @NonNull
+ @Nullable
public IpConfiguration getIpConfiguration() {
- return new IpConfiguration(mIpConfig);
+ return mIpConfig == null ? null : new IpConfiguration(mIpConfig);
}
/**
@@ -57,9 +60,8 @@
return mNetworkCapabilities == null ? null : new NetworkCapabilities(mNetworkCapabilities);
}
- private EthernetNetworkUpdateRequest(@NonNull final IpConfiguration ipConfig,
+ private EthernetNetworkUpdateRequest(@Nullable final IpConfiguration ipConfig,
@Nullable final NetworkCapabilities networkCapabilities) {
- Objects.requireNonNull(ipConfig);
mIpConfig = ipConfig;
mNetworkCapabilities = networkCapabilities;
}
@@ -90,7 +92,8 @@
*/
public Builder(@NonNull final EthernetNetworkUpdateRequest request) {
Objects.requireNonNull(request);
- mBuilderIpConfig = new IpConfiguration(request.mIpConfig);
+ mBuilderIpConfig = null == request.mIpConfig
+ ? null : new IpConfiguration(request.mIpConfig);
mBuilderNetworkCapabilities = null == request.mNetworkCapabilities
? null : new NetworkCapabilities(request.mNetworkCapabilities);
}
@@ -101,8 +104,8 @@
* @return The builder to facilitate chaining.
*/
@NonNull
- public Builder setIpConfiguration(@NonNull final IpConfiguration ipConfig) {
- mBuilderIpConfig = new IpConfiguration(ipConfig);
+ public Builder setIpConfiguration(@Nullable final IpConfiguration ipConfig) {
+ mBuilderIpConfig = ipConfig == null ? null : new IpConfiguration(ipConfig);
return this;
}
@@ -119,9 +122,16 @@
/**
* Build {@link EthernetNetworkUpdateRequest} return the current update request.
+ *
+ * @throws IllegalStateException when both mBuilderNetworkCapabilities and mBuilderIpConfig
+ * are null.
*/
@NonNull
public EthernetNetworkUpdateRequest build() {
+ if (mBuilderIpConfig == null && mBuilderNetworkCapabilities == null) {
+ throw new IllegalStateException(
+ "Cannot construct an empty EthernetNetworkUpdateRequest");
+ }
return new EthernetNetworkUpdateRequest(mBuilderIpConfig, mBuilderNetworkCapabilities);
}
}
diff --git a/packages/ConnectivityT/framework-t/src/android/net/IEthernetManager.aidl b/packages/ConnectivityT/framework-t/src/android/net/IEthernetManager.aidl
index 544d02b..42e4c1a 100644
--- a/packages/ConnectivityT/framework-t/src/android/net/IEthernetManager.aidl
+++ b/packages/ConnectivityT/framework-t/src/android/net/IEthernetManager.aidl
@@ -18,10 +18,13 @@
import android.net.IpConfiguration;
import android.net.IEthernetServiceListener;
-import android.net.IEthernetNetworkManagementListener;
+import android.net.EthernetNetworkManagementException;
import android.net.EthernetNetworkUpdateRequest;
+import android.net.INetworkInterfaceOutcomeReceiver;
import android.net.ITetheredInterfaceCallback;
+import java.util.List;
+
/**
* Interface that answers queries about, and allows changing
* ethernet configuration.
@@ -39,7 +42,9 @@
void requestTetheredInterface(in ITetheredInterfaceCallback callback);
void releaseTetheredInterface(in ITetheredInterfaceCallback callback);
void updateConfiguration(String iface, in EthernetNetworkUpdateRequest request,
- in IEthernetNetworkManagementListener listener);
- void connectNetwork(String iface, in IEthernetNetworkManagementListener listener);
- void disconnectNetwork(String iface, in IEthernetNetworkManagementListener listener);
+ in INetworkInterfaceOutcomeReceiver listener);
+ void connectNetwork(String iface, in INetworkInterfaceOutcomeReceiver listener);
+ void disconnectNetwork(String iface, in INetworkInterfaceOutcomeReceiver listener);
+ void setEthernetEnabled(boolean enabled);
+ List<String> getInterfaceList();
}
diff --git a/packages/ConnectivityT/framework-t/src/android/net/IEthernetServiceListener.aidl b/packages/ConnectivityT/framework-t/src/android/net/IEthernetServiceListener.aidl
index 6d2ba03..751605b 100644
--- a/packages/ConnectivityT/framework-t/src/android/net/IEthernetServiceListener.aidl
+++ b/packages/ConnectivityT/framework-t/src/android/net/IEthernetServiceListener.aidl
@@ -21,6 +21,7 @@
/** @hide */
oneway interface IEthernetServiceListener
{
+ void onEthernetStateChanged(int state);
void onInterfaceStateChanged(String iface, int state, int role,
in IpConfiguration configuration);
}
diff --git a/packages/ConnectivityT/framework-t/src/android/net/IEthernetNetworkManagementListener.aidl b/packages/ConnectivityT/framework-t/src/android/net/INetworkInterfaceOutcomeReceiver.aidl
similarity index 80%
rename from packages/ConnectivityT/framework-t/src/android/net/IEthernetNetworkManagementListener.aidl
rename to packages/ConnectivityT/framework-t/src/android/net/INetworkInterfaceOutcomeReceiver.aidl
index 93edccf..85795ea 100644
--- a/packages/ConnectivityT/framework-t/src/android/net/IEthernetNetworkManagementListener.aidl
+++ b/packages/ConnectivityT/framework-t/src/android/net/INetworkInterfaceOutcomeReceiver.aidl
@@ -17,9 +17,9 @@
package android.net;
import android.net.EthernetNetworkManagementException;
-import android.net.Network;
/** @hide */
-oneway interface IEthernetNetworkManagementListener {
- void onComplete(in Network network, in EthernetNetworkManagementException exception);
+oneway interface INetworkInterfaceOutcomeReceiver {
+ void onResult(in String iface);
+ void onError(in EthernetNetworkManagementException e);
}
\ No newline at end of file
diff --git a/packages/ConnectivityT/framework-t/src/android/net/INetworkStatsService.aidl b/packages/ConnectivityT/framework-t/src/android/net/INetworkStatsService.aidl
index efe626d..c86f7fd 100644
--- a/packages/ConnectivityT/framework-t/src/android/net/INetworkStatsService.aidl
+++ b/packages/ConnectivityT/framework-t/src/android/net/INetworkStatsService.aidl
@@ -91,7 +91,7 @@
in INetworkStatsProvider provider);
/** Mark given UID as being in foreground for stats purposes. */
- void setUidForeground(int uid, boolean uidForeground);
+ void noteUidForeground(int uid, boolean uidForeground);
/** Advise persistence threshold; may be overridden internally. */
void advisePersistThreshold(long thresholdBytes);
diff --git a/packages/ConnectivityT/framework-t/src/android/net/NetworkStats.java b/packages/ConnectivityT/framework-t/src/android/net/NetworkStats.java
index f681ba1..bcfeab9 100644
--- a/packages/ConnectivityT/framework-t/src/android/net/NetworkStats.java
+++ b/packages/ConnectivityT/framework-t/src/android/net/NetworkStats.java
@@ -16,6 +16,8 @@
package android.net;
+import static android.annotation.SystemApi.Client.MODULE_LIBRARIES;
+
import static com.android.net.module.util.NetworkStatsUtils.multiplySafeByRational;
import android.annotation.IntDef;
@@ -124,7 +126,6 @@
public @Nullable static final String[] INTERFACES_ALL = null;
/** {@link #tag} value for total data across all tags. */
- // TODO: Rename TAG_NONE to TAG_ALL.
public static final int TAG_NONE = 0;
/** {@link #metered} value to account for all metered states. */
@@ -327,16 +328,11 @@
* @param uid uid of this {@link Entry}. {@link #UID_TETHERING} if this {@link Entry} is
* for tethering. Or {@link #UID_ALL} if this {@link NetworkStats} is only
* counting iface stats.
- * @param set usage state of this {@link Entry}. Should be one of the following
- * values: {@link #SET_DEFAULT}, {@link #SET_FOREGROUND}.
+ * @param set usage state of this {@link Entry}.
* @param tag tag of this {@link Entry}.
- * @param metered metered state of this {@link Entry}. Should be one of the following
- * values: {link #METERED_YES}, {link #METERED_NO}.
- * @param roaming roaming state of this {@link Entry}. Should be one of the following
- * values: {link #ROAMING_YES}, {link #ROAMING_NO}.
- * @param defaultNetwork default network status of this {@link Entry}. Should be one
- * of the following values: {link #DEFAULT_NETWORK_YES},
- * {link #DEFAULT_NETWORK_NO}.
+ * @param metered metered state of this {@link Entry}.
+ * @param roaming roaming state of this {@link Entry}.
+ * @param defaultNetwork default network status of this {@link Entry}.
* @param rxBytes Number of bytes received for this {@link Entry}. Statistics should
* represent the contents of IP packets, including IP headers.
* @param rxPackets Number of packets received for this {@link Entry}. Statistics should
@@ -395,81 +391,102 @@
/**
* @return the uid of this entry.
+ * @hide
*/
+ @SystemApi(client = MODULE_LIBRARIES)
public int getUid() {
return uid;
}
/**
- * @return the set state of this entry. Should be one of the following
- * values: {@link #SET_DEFAULT}, {@link #SET_FOREGROUND}.
+ * @return the set state of this entry.
+ * @hide
*/
+ @SystemApi(client = MODULE_LIBRARIES)
@State public int getSet() {
return set;
}
/**
* @return the tag value of this entry.
+ * @hide
*/
+ @SystemApi(client = MODULE_LIBRARIES)
public int getTag() {
return tag;
}
/**
- * @return the metered state. Should be one of the following
- * values: {link #METERED_YES}, {link #METERED_NO}.
+ * @return the metered state.
+ * @hide
*/
- @Meteredness public int getMetered() {
+ @Meteredness
+ @SystemApi(client = MODULE_LIBRARIES)
+ public int getMetered() {
return metered;
}
/**
- * @return the roaming state. Should be one of the following
- * values: {link #ROAMING_YES}, {link #ROAMING_NO}.
+ * @return the roaming state.
+ * @hide
*/
- @Roaming public int getRoaming() {
+ @Roaming
+ @SystemApi(client = MODULE_LIBRARIES)
+ public int getRoaming() {
return roaming;
}
/**
- * @return the default network state. Should be one of the following
- * values: {link #DEFAULT_NETWORK_YES}, {link #DEFAULT_NETWORK_NO}.
+ * @return the default network state.
+ * @hide
*/
- @DefaultNetwork public int getDefaultNetwork() {
+ @DefaultNetwork
+ @SystemApi(client = MODULE_LIBRARIES)
+ public int getDefaultNetwork() {
return defaultNetwork;
}
/**
* @return the number of received bytes.
+ * @hide
*/
+ @SystemApi(client = MODULE_LIBRARIES)
public long getRxBytes() {
return rxBytes;
}
/**
* @return the number of received packets.
+ * @hide
*/
+ @SystemApi(client = MODULE_LIBRARIES)
public long getRxPackets() {
return rxPackets;
}
/**
* @return the number of transmitted bytes.
+ * @hide
*/
+ @SystemApi(client = MODULE_LIBRARIES)
public long getTxBytes() {
return txBytes;
}
/**
* @return the number of transmitted packets.
+ * @hide
*/
+ @SystemApi(client = MODULE_LIBRARIES)
public long getTxPackets() {
return txPackets;
}
/**
* @return the count of network operations performed for this entry.
+ * @hide
*/
+ @SystemApi(client = MODULE_LIBRARIES)
public long getOperations() {
return operations;
}
@@ -691,7 +708,7 @@
* The remove() method is not implemented and will throw UnsupportedOperationException.
* @hide
*/
- @SystemApi
+ @SystemApi(client = MODULE_LIBRARIES)
@NonNull public Iterator<Entry> iterator() {
return new Iterator<Entry>() {
int mIndex = 0;
diff --git a/packages/ConnectivityT/framework-t/src/android/net/TrafficStats.java b/packages/ConnectivityT/framework-t/src/android/net/TrafficStats.java
index bc836d8..dc4ac55 100644
--- a/packages/ConnectivityT/framework-t/src/android/net/TrafficStats.java
+++ b/packages/ConnectivityT/framework-t/src/android/net/TrafficStats.java
@@ -205,7 +205,7 @@
* server context.
* @hide
*/
- @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES)
+ @SystemApi(client = MODULE_LIBRARIES)
@SuppressLint("VisiblySynchronized")
public static synchronized void init(@NonNull final Context context) {
if (sStatsService != null) {
@@ -376,7 +376,7 @@
*
* @hide
*/
- @SystemApi
+ @SystemApi(client = MODULE_LIBRARIES)
public static void setThreadStatsTagDownload() {
setThreadStatsTag(TAG_SYSTEM_DOWNLOAD);
}
@@ -468,7 +468,7 @@
*
* @see #setThreadStatsTag(int)
*/
- public static void tagSocket(Socket socket) throws SocketException {
+ public static void tagSocket(@NonNull Socket socket) throws SocketException {
SocketTagger.get().tag(socket);
}
@@ -483,7 +483,7 @@
* calling {@code untagSocket()} before sending the socket to another
* process.
*/
- public static void untagSocket(Socket socket) throws SocketException {
+ public static void untagSocket(@NonNull Socket socket) throws SocketException {
SocketTagger.get().untag(socket);
}
@@ -496,14 +496,14 @@
*
* @see #setThreadStatsTag(int)
*/
- public static void tagDatagramSocket(DatagramSocket socket) throws SocketException {
+ public static void tagDatagramSocket(@NonNull DatagramSocket socket) throws SocketException {
SocketTagger.get().tag(socket);
}
/**
* Remove any statistics parameters from the given {@link DatagramSocket}.
*/
- public static void untagDatagramSocket(DatagramSocket socket) throws SocketException {
+ public static void untagDatagramSocket(@NonNull DatagramSocket socket) throws SocketException {
SocketTagger.get().untag(socket);
}
@@ -516,7 +516,7 @@
*
* @see #setThreadStatsTag(int)
*/
- public static void tagFileDescriptor(FileDescriptor fd) throws IOException {
+ public static void tagFileDescriptor(@NonNull FileDescriptor fd) throws IOException {
SocketTagger.get().tag(fd);
}
@@ -524,7 +524,7 @@
* Remove any statistics parameters from the given {@link FileDescriptor}
* socket.
*/
- public static void untagFileDescriptor(FileDescriptor fd) throws IOException {
+ public static void untagFileDescriptor(@NonNull FileDescriptor fd) throws IOException {
SocketTagger.get().untag(fd);
}
diff --git a/packages/ConnectivityT/framework-t/src/android/net/netstats/provider/INetworkStatsProviderCallback.aidl b/packages/ConnectivityT/framework-t/src/android/net/netstats/provider/INetworkStatsProviderCallback.aidl
index 7eaa01e..01ff02d 100644
--- a/packages/ConnectivityT/framework-t/src/android/net/netstats/provider/INetworkStatsProviderCallback.aidl
+++ b/packages/ConnectivityT/framework-t/src/android/net/netstats/provider/INetworkStatsProviderCallback.aidl
@@ -26,6 +26,7 @@
oneway interface INetworkStatsProviderCallback {
void notifyStatsUpdated(int token, in NetworkStats ifaceStats, in NetworkStats uidStats);
void notifyAlertReached();
- void notifyWarningOrLimitReached();
+ void notifyWarningReached();
+ void notifyLimitReached();
void unregister();
}
diff --git a/packages/ConnectivityT/framework-t/src/android/net/netstats/provider/NetworkStatsProvider.java b/packages/ConnectivityT/framework-t/src/android/net/netstats/provider/NetworkStatsProvider.java
index 23fc069..d37a53d 100644
--- a/packages/ConnectivityT/framework-t/src/android/net/netstats/provider/NetworkStatsProvider.java
+++ b/packages/ConnectivityT/framework-t/src/android/net/netstats/provider/NetworkStatsProvider.java
@@ -152,19 +152,19 @@
try {
// Reuse the code path to notify warning reached with limit reached
// since framework handles them in the same way.
- getProviderCallbackBinderOrThrow().notifyWarningOrLimitReached();
+ getProviderCallbackBinderOrThrow().notifyWarningReached();
} catch (RemoteException e) {
e.rethrowAsRuntimeException();
}
}
/**
- * Notify system that the quota set by {@link #onSetLimit} or limit set by
+ * Notify system that the limit set by {@link #onSetLimit} or limit set by
* {@link #onSetWarningAndLimit} has been reached.
*/
public void notifyLimitReached() {
try {
- getProviderCallbackBinderOrThrow().notifyWarningOrLimitReached();
+ getProviderCallbackBinderOrThrow().notifyLimitReached();
} catch (RemoteException e) {
e.rethrowAsRuntimeException();
}
diff --git a/packages/ConnectivityT/service/src/com/android/server/net/NetworkStatsService.java b/packages/ConnectivityT/service/src/com/android/server/net/NetworkStatsService.java
index 1d22908..e3794e4 100644
--- a/packages/ConnectivityT/service/src/com/android/server/net/NetworkStatsService.java
+++ b/packages/ConnectivityT/service/src/com/android/server/net/NetworkStatsService.java
@@ -1194,7 +1194,7 @@
}
@VisibleForTesting
- public void setUidForeground(int uid, boolean uidForeground) {
+ public void noteUidForeground(int uid, boolean uidForeground) {
PermissionUtils.enforceNetworkStackPermission(mContext);
synchronized (mStatsLock) {
final int set = uidForeground ? SET_FOREGROUND : SET_DEFAULT;
@@ -2393,10 +2393,17 @@
}
@Override
- public void notifyWarningOrLimitReached() {
- Log.d(TAG, mTag + ": notifyWarningOrLimitReached");
+ public void notifyWarningReached() {
+ Log.d(TAG, mTag + ": notifyWarningReached");
BinderUtils.withCleanCallingIdentity(() ->
- mNetworkPolicyManager.notifyStatsProviderWarningOrLimitReached());
+ mNetworkPolicyManager.notifyStatsProviderWarningReached());
+ }
+
+ @Override
+ public void notifyLimitReached() {
+ Log.d(TAG, mTag + ": notifyLimitReached");
+ BinderUtils.withCleanCallingIdentity(() ->
+ mNetworkPolicyManager.notifyStatsProviderLimitReached());
}
@Override
diff --git a/packages/DynamicSystemInstallationService/Android.bp b/packages/DynamicSystemInstallationService/Android.bp
index ad86f46..b8f54b3 100644
--- a/packages/DynamicSystemInstallationService/Android.bp
+++ b/packages/DynamicSystemInstallationService/Android.bp
@@ -22,6 +22,9 @@
defaults: ["platform_app_defaults"],
srcs: ["src/**/*.java"],
+ static_libs: [
+ "DynamicSystemInstallationService-logtags",
+ ],
resource_dirs: ["res"],
certificate: "platform",
@@ -32,3 +35,8 @@
enabled: false,
},
}
+
+java_library {
+ name: "DynamicSystemInstallationService-logtags",
+ srcs: ["src/**/*.logtags"],
+}
diff --git a/packages/DynamicSystemInstallationService/src/com/android/dynsystem/DynamicSystemInstallationService.java b/packages/DynamicSystemInstallationService/src/com/android/dynsystem/DynamicSystemInstallationService.java
index f8cb5d3..02128d4 100644
--- a/packages/DynamicSystemInstallationService/src/com/android/dynsystem/DynamicSystemInstallationService.java
+++ b/packages/DynamicSystemInstallationService/src/com/android/dynsystem/DynamicSystemInstallationService.java
@@ -58,6 +58,7 @@
import android.os.image.DynamicSystemClient;
import android.os.image.DynamicSystemManager;
import android.text.TextUtils;
+import android.util.EventLog;
import android.util.Log;
import android.widget.Toast;
@@ -104,6 +105,36 @@
private static final int NOTIFICATION_ID = 1;
/*
+ * Event log tags
+ */
+ private static final int EVENT_DSU_PROGRESS_UPDATE = 120000;
+ private static final int EVENT_DSU_INSTALL_COMPLETE = 120001;
+ private static final int EVENT_DSU_INSTALL_FAILED = 120002;
+
+ protected static void logEventProgressUpdate(
+ String partition,
+ long installedSize,
+ long partitionSize,
+ int partitionNumber,
+ int totalPartitionNumber) {
+ EventLog.writeEvent(
+ EVENT_DSU_PROGRESS_UPDATE,
+ partition,
+ installedSize,
+ partitionSize,
+ partitionNumber,
+ totalPartitionNumber);
+ }
+
+ protected static void logEventComplete() {
+ EventLog.writeEvent(EVENT_DSU_INSTALL_COMPLETE);
+ }
+
+ protected static void logEventFailed(String cause) {
+ EventLog.writeEvent(EVENT_DSU_INSTALL_FAILED, cause);
+ }
+
+ /*
* IPC
*/
/** Keeps track of all current registered clients. */
@@ -132,15 +163,10 @@
private DynamicSystemManager mDynSystem;
private NotificationManager mNM;
- private int mNumInstalledPartitions;
-
- private String mCurrentPartitionName;
- private long mCurrentPartitionSize;
- private long mCurrentPartitionInstalledSize;
-
// This is for testing only now
private boolean mEnableWhenCompleted;
+ private InstallationAsyncTask.Progress mInstallTaskProgress;
private InstallationAsyncTask mInstallTask;
@@ -203,17 +229,21 @@
@Override
public void onProgressUpdate(InstallationAsyncTask.Progress progress) {
- mCurrentPartitionName = progress.partitionName;
- mCurrentPartitionSize = progress.partitionSize;
- mCurrentPartitionInstalledSize = progress.installedSize;
- mNumInstalledPartitions = progress.numInstalledPartitions;
+ logEventProgressUpdate(
+ progress.partitionName,
+ progress.installedSize,
+ progress.partitionSize,
+ progress.partitionNumber,
+ progress.totalPartitionNumber);
+ mInstallTaskProgress = progress;
postStatus(STATUS_IN_PROGRESS, CAUSE_NOT_SPECIFIED, null);
}
@Override
public void onResult(int result, Throwable detail) {
if (result == RESULT_OK) {
+ logEventComplete();
postStatus(STATUS_READY, CAUSE_INSTALL_COMPLETED, null);
// For testing: enable DSU and restart the device when install completed
@@ -223,6 +253,12 @@
return;
}
+ if (result == RESULT_CANCELLED) {
+ logEventFailed("Dynamic System installation task is canceled by the user.");
+ } else {
+ logEventFailed("error: " + detail);
+ }
+
boolean removeNotification = false;
switch (result) {
case RESULT_CANCELLED:
@@ -251,16 +287,20 @@
private void executeInstallCommand(Intent intent) {
if (!verifyRequest(intent)) {
Log.e(TAG, "Verification failed. Did you use VerificationActivity?");
+ logEventFailed("VerificationActivity");
return;
}
if (mInstallTask != null) {
Log.e(TAG, "There is already an installation task running");
+ logEventFailed("There is already an ongoing installation task.");
return;
}
if (isInDynamicSystem()) {
Log.e(TAG, "We are already running in DynamicSystem");
+ logEventFailed(
+ "Cannot start a Dynamic System installation task within a Dynamic System.");
return;
}
@@ -445,19 +485,22 @@
case STATUS_IN_PROGRESS:
builder.setContentText(getString(R.string.notification_install_inprogress));
- int max = 1024;
- int progress = 0;
+ if (mInstallTaskProgress != null) {
+ int max = 1024;
+ int progress = 0;
- int currentMax = max >> (mNumInstalledPartitions + 1);
- progress = max - currentMax * 2;
+ int currentMax = max >> mInstallTaskProgress.partitionNumber;
+ progress = max - currentMax * 2;
- long currentProgress = (mCurrentPartitionInstalledSize >> 20) * currentMax
- / Math.max(mCurrentPartitionSize >> 20, 1);
+ long currentProgress =
+ (mInstallTaskProgress.installedSize >> 20)
+ * currentMax
+ / Math.max(mInstallTaskProgress.partitionSize >> 20, 1);
- progress += (int) currentProgress;
+ progress += (int) currentProgress;
- builder.setProgress(max, progress, false);
-
+ builder.setProgress(max, progress, false);
+ }
builder.addAction(new Notification.Action.Builder(
null, getString(R.string.notification_action_cancel),
createPendingIntent(ACTION_CANCEL_INSTALL)).build());
@@ -563,13 +606,13 @@
StringBuilder msg = new StringBuilder();
msg.append("status: " + statusString + ", cause: " + causeString);
- if (status == STATUS_IN_PROGRESS) {
+ if (status == STATUS_IN_PROGRESS && mInstallTaskProgress != null) {
msg.append(
String.format(
", partition name: %s, progress: %d/%d",
- mCurrentPartitionName,
- mCurrentPartitionInstalledSize,
- mCurrentPartitionSize));
+ mInstallTaskProgress.partitionName,
+ mInstallTaskProgress.installedSize,
+ mInstallTaskProgress.partitionSize));
}
if (detail != null) {
msg.append(", detail: " + detail);
@@ -594,7 +637,10 @@
Bundle bundle = new Bundle();
// TODO: send more info to the clients
- bundle.putLong(DynamicSystemClient.KEY_INSTALLED_SIZE, mCurrentPartitionInstalledSize);
+ if (mInstallTaskProgress != null) {
+ bundle.putLong(
+ DynamicSystemClient.KEY_INSTALLED_SIZE, mInstallTaskProgress.installedSize);
+ }
if (detail != null) {
bundle.putSerializable(DynamicSystemClient.KEY_EXCEPTION_DETAIL,
diff --git a/packages/DynamicSystemInstallationService/src/com/android/dynsystem/EventLogTags.logtags b/packages/DynamicSystemInstallationService/src/com/android/dynsystem/EventLogTags.logtags
new file mode 100644
index 0000000..eae9de9
--- /dev/null
+++ b/packages/DynamicSystemInstallationService/src/com/android/dynsystem/EventLogTags.logtags
@@ -0,0 +1,7 @@
+# See system/logging/logcat/event.logtags for a description of the format of this file.
+
+option java_package com.android.dynsystem
+
+120000 dsu_progress_update (partition|3),(installed_size|2|5),(partition_size|2|5),(partition_number|1|5),(total_partition_number|1|5)
+120001 dsu_install_complete
+120002 dsu_install_failed (cause|3)
diff --git a/packages/DynamicSystemInstallationService/src/com/android/dynsystem/InstallationAsyncTask.java b/packages/DynamicSystemInstallationService/src/com/android/dynsystem/InstallationAsyncTask.java
index f18d426..b439f84 100644
--- a/packages/DynamicSystemInstallationService/src/com/android/dynsystem/InstallationAsyncTask.java
+++ b/packages/DynamicSystemInstallationService/src/com/android/dynsystem/InstallationAsyncTask.java
@@ -44,7 +44,7 @@
import java.util.zip.ZipFile;
import java.util.zip.ZipInputStream;
-class InstallationAsyncTask extends AsyncTask<String, InstallationAsyncTask.Progress, Throwable> {
+class InstallationAsyncTask extends AsyncTask<String, Long, Throwable> {
private static final String TAG = "InstallationAsyncTask";
@@ -106,14 +106,22 @@
static class Progress {
public final String partitionName;
+ public final long installedSize;
public final long partitionSize;
- public final int numInstalledPartitions;
- public long installedSize;
+ public final int partitionNumber;
+ public final int totalPartitionNumber;
- Progress(String partitionName, long partitionSize, int numInstalledPartitions) {
+ Progress(
+ String partitionName,
+ long installedSize,
+ long partitionSize,
+ int partitionNumber,
+ int totalPartitionNumber) {
this.partitionName = partitionName;
+ this.installedSize = installedSize;
this.partitionSize = partitionSize;
- this.numInstalledPartitions = numInstalledPartitions;
+ this.partitionNumber = partitionNumber;
+ this.totalPartitionNumber = totalPartitionNumber;
}
}
@@ -139,7 +147,10 @@
private boolean mIsZip;
private boolean mIsCompleted;
- private int mNumInstalledPartitions;
+ private String mPartitionName;
+ private long mPartitionSize;
+ private int mPartitionNumber;
+ private int mTotalPartitionNumber;
private InputStream mStream;
private ZipFile mZipFile;
@@ -175,11 +186,15 @@
protected Throwable doInBackground(String... voids) {
Log.d(TAG, "Start doInBackground(), URL: " + mUrl);
+ final boolean wantScratchPartition = Build.IS_DEBUGGABLE;
try {
// call DynamicSystemManager to cleanup stuff
mDynSystem.remove();
verifyAndPrepare();
+ if (wantScratchPartition) {
+ ++mTotalPartitionNumber;
+ }
mDynSystem.startInstallation(mDsuSlot);
@@ -198,7 +213,7 @@
return null;
}
- if (Build.IS_DEBUGGABLE) {
+ if (wantScratchPartition) {
// If host is debuggable, then install a scratch partition so that we can do
// adb remount in the guest system.
try {
@@ -262,9 +277,14 @@
}
@Override
- protected void onProgressUpdate(Progress... values) {
- Progress progress = values[0];
- mListener.onProgressUpdate(progress);
+ protected void onProgressUpdate(Long... installedSize) {
+ mListener.onProgressUpdate(
+ new Progress(
+ mPartitionName,
+ installedSize[0],
+ mPartitionSize,
+ mPartitionNumber,
+ mTotalPartitionNumber));
}
private void verifyAndPrepare() throws Exception {
@@ -281,12 +301,16 @@
throw new UnsupportedFormatException(
String.format(Locale.US, "Unsupported file format: %s", mUrl));
}
+ // At least two partitions, {system, userdata}
+ mTotalPartitionNumber = 2;
if (mIsNetworkUrl) {
mStream = new URL(mUrl).openStream();
} else if (URLUtil.isFileUrl(mUrl)) {
if (mIsZip) {
mZipFile = new ZipFile(new File(new URL(mUrl).toURI()));
+ // {*.img in zip} + {userdata}
+ mTotalPartitionNumber = calculateNumberOfImagesInLocalZip(mZipFile) + 1;
} else {
mStream = new URL(mUrl).openStream();
}
@@ -333,9 +357,13 @@
}
};
- thread.start();
- Progress progress = new Progress(partitionName, partitionSize, mNumInstalledPartitions++);
+ mPartitionName = partitionName;
+ mPartitionSize = partitionSize;
+ ++mPartitionNumber;
+ publishProgress(/* installedSize = */ 0L);
+ long prevInstalledSize = 0;
+ thread.start();
while (thread.isAlive()) {
if (isCancelled()) {
return;
@@ -343,9 +371,9 @@
final long installedSize = mDynSystem.getInstallationProgress().bytes_processed;
- if (installedSize > progress.installedSize + MIN_PROGRESS_TO_PUBLISH) {
- progress.installedSize = installedSize;
- publishProgress(progress);
+ if (installedSize > prevInstalledSize + MIN_PROGRESS_TO_PUBLISH) {
+ publishProgress(installedSize);
+ prevInstalledSize = installedSize;
}
try {
@@ -392,14 +420,42 @@
installImage("system", mSystemSize, new GZIPInputStream(mStream));
}
+ private boolean shouldInstallEntry(String name) {
+ if (!name.endsWith(".img")) {
+ return false;
+ }
+ String partitionName = name.substring(0, name.length() - 4);
+ if (UNSUPPORTED_PARTITIONS.contains(partitionName)) {
+ return false;
+ }
+ return true;
+ }
+
+ private int calculateNumberOfImagesInLocalZip(ZipFile zipFile) {
+ int total = 0;
+ Enumeration<? extends ZipEntry> entries = zipFile.entries();
+ while (entries.hasMoreElements()) {
+ ZipEntry entry = entries.nextElement();
+ if (shouldInstallEntry(entry.getName())) {
+ ++total;
+ }
+ }
+ return total;
+ }
+
private void installStreamingZipUpdate() throws IOException, ImageValidationException {
Log.d(TAG, "To install a streaming ZIP update");
ZipInputStream zis = new ZipInputStream(mStream);
- ZipEntry zipEntry = null;
+ ZipEntry entry = null;
- while ((zipEntry = zis.getNextEntry()) != null) {
- installImageFromAnEntry(zipEntry, zis);
+ while ((entry = zis.getNextEntry()) != null) {
+ String name = entry.getName();
+ if (shouldInstallEntry(name)) {
+ installImageFromAnEntry(entry, zis);
+ } else {
+ Log.d(TAG, name + " installation is not supported, skip it.");
+ }
if (isCancelled()) {
break;
@@ -414,7 +470,12 @@
while (entries.hasMoreElements()) {
ZipEntry entry = entries.nextElement();
- installImageFromAnEntry(entry, mZipFile.getInputStream(entry));
+ String name = entry.getName();
+ if (shouldInstallEntry(name)) {
+ installImageFromAnEntry(entry, mZipFile.getInputStream(entry));
+ } else {
+ Log.d(TAG, name + " installation is not supported, skip it.");
+ }
if (isCancelled()) {
break;
@@ -422,28 +483,16 @@
}
}
- private boolean installImageFromAnEntry(ZipEntry entry, InputStream is)
+ private void installImageFromAnEntry(ZipEntry entry, InputStream is)
throws IOException, ImageValidationException {
String name = entry.getName();
Log.d(TAG, "ZipEntry: " + name);
- if (!name.endsWith(".img")) {
- return false;
- }
-
String partitionName = name.substring(0, name.length() - 4);
-
- if (UNSUPPORTED_PARTITIONS.contains(partitionName)) {
- Log.d(TAG, name + " installation is not supported, skip it.");
- return false;
- }
-
long uncompressedSize = entry.getSize();
installImage(partitionName, uncompressedSize, is);
-
- return true;
}
private void installImage(String partitionName, long uncompressedSize, InputStream is)
@@ -497,8 +546,12 @@
mInstallationSession.setAshmem(pfd, READ_BUFFER_SIZE);
- Progress progress = new Progress(partitionName, partitionSize, mNumInstalledPartitions++);
+ mPartitionName = partitionName;
+ mPartitionSize = partitionSize;
+ ++mPartitionNumber;
+ publishProgress(/* installedSize = */ 0L);
+ long prevInstalledSize = 0;
long installedSize = 0;
byte[] bytes = new byte[READ_BUFFER_SIZE];
int numBytesRead;
@@ -516,9 +569,9 @@
installedSize += numBytesRead;
- if (installedSize > progress.installedSize + MIN_PROGRESS_TO_PUBLISH) {
- progress.installedSize = installedSize;
- publishProgress(progress);
+ if (installedSize > prevInstalledSize + MIN_PROGRESS_TO_PUBLISH) {
+ publishProgress(installedSize);
+ prevInstalledSize = installedSize;
}
}
diff --git a/packages/PackageInstaller/res/values-ar/strings.xml b/packages/PackageInstaller/res/values-ar/strings.xml
index 2d6fca6..51b18d3 100644
--- a/packages/PackageInstaller/res/values-ar/strings.xml
+++ b/packages/PackageInstaller/res/values-ar/strings.xml
@@ -59,7 +59,7 @@
<string name="uninstall_application_text_current_user_work_profile" msgid="8788387739022366193">"هل تريد إزالة تثبيت هذا التطبيق من ملفك الشخصي للعمل؟"</string>
<string name="uninstall_update_text" msgid="863648314632448705">"هل تريد استبدال هذا التطبيق بإصدار المصنع؟ ستتم إزالة جميع البيانات."</string>
<string name="uninstall_update_text_multiuser" msgid="8992883151333057227">"هل تريد إعادة ضبط هذا التطبيق على الإعدادات الأصلية؟ سؤدي ذلك إلى إزالة جميع البيانات، كما سيؤثر على جميع مستخدمي هذا الجهاز، بما في ذلك من لديهم ملفات شخصية للعمل."</string>
- <string name="uninstall_keep_data" msgid="7002379587465487550">"الاحتفاظ بالحجم <xliff:g id="SIZE">%1$s</xliff:g> من بيانات التطبيق."</string>
+ <string name="uninstall_keep_data" msgid="7002379587465487550">"الاحتفاظ بـ <xliff:g id="SIZE">%1$s</xliff:g> من بيانات التطبيق."</string>
<string name="uninstalling_notification_channel" msgid="840153394325714653">"عمليات إلغاء التثبيت الجارية"</string>
<string name="uninstall_failure_notification_channel" msgid="1136405866767576588">"عمليات إلغاء التثبيت غير الناجحة"</string>
<string name="uninstalling" msgid="8709566347688966845">"جارٍ إلغاء التثبيت…"</string>
diff --git a/packages/PackageInstaller/res/values-or/strings.xml b/packages/PackageInstaller/res/values-or/strings.xml
index 20a3480..ca01d7f 100644
--- a/packages/PackageInstaller/res/values-or/strings.xml
+++ b/packages/PackageInstaller/res/values-or/strings.xml
@@ -88,7 +88,7 @@
<string name="anonymous_source_warning" product="tablet" msgid="3939101621438855516">"ଅଜଣା ଆପ୍ ଦ୍ୱାରା ଆପଣଙ୍କ ଟାବଲେଟ୍ ଏବଂ ବ୍ୟକ୍ତିଗତ ଡାଟାକୁ ନଷ୍ଟ କରାଯାଇପାରିବାର ସମ୍ଭାବନା ବହୁତ ଅଧିକ। ଏହି ଆପ୍କୁ ଇନଷ୍ଟଲ୍ କରିବାର ଅର୍ଥ ହେଉଛି ଆପଣଙ୍କ ଟାବ୍ଲେଟ୍ରେ ଘଟିବା କୌଣସି ପ୍ରକାର କ୍ଷତି କିମ୍ବା ସେଗୁଡ଼ିକର ବ୍ୟବହାରରୁ ହେବା କୌଣସି ପ୍ରକାର ଡାଟାର ହାନୀ ପାଇଁ ଆପଣ ଦାୟୀ ରହିବାକୁ ରାଜି ହୁଅନ୍ତି।"</string>
<string name="anonymous_source_warning" product="tv" msgid="5599483539528168566">"ଅଜଣା ଆପ୍ ଦ୍ୱାରା ଆପଣଙ୍କ ଟିଭି ଏବଂ ବ୍ୟକ୍ତିଗତ ଡାଟାକୁ ନଷ୍ଟ କରାଯାଇପାରିବାର ସମ୍ଭାବନା ବହୁତ ଅଧିକ। ଏହି ଆପ୍କୁ ଇନଷ୍ଟଲ୍ କରିବାର ଅର୍ଥ ହେଉଛି ଆପଣଙ୍କ ଟିଭିରେ ଘଟିବା କୌଣସି ପ୍ରକାର କ୍ଷତି କିମ୍ବା ସେଗୁଡ଼ିକର ବ୍ୟବହାରରୁ ହେବା କୌଣସି ପ୍ରକାର ଡାଟାର ହାନୀ ପାଇଁ ଆପଣ ଦାୟୀ ରହିବାକୁ ରାଜି ହୁଅନ୍ତି।"</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/PrintSpooler/res/values-it/strings.xml b/packages/PrintSpooler/res/values-it/strings.xml
index 40b621c..d898b1e 100644
--- a/packages/PrintSpooler/res/values-it/strings.xml
+++ b/packages/PrintSpooler/res/values-it/strings.xml
@@ -56,8 +56,8 @@
<string name="print_select_printer" msgid="7388760939873368698">"Seleziona stampante"</string>
<string name="print_forget_printer" msgid="5035287497291910766">"Elimina stampante"</string>
<plurals name="print_search_result_count_utterance" formatted="false" msgid="6997663738361080868">
- <item quantity="one"><xliff:g id="COUNT_1">%1$s</xliff:g> printers found</item>
<item quantity="other"><xliff:g id="COUNT_1">%1$s</xliff:g> stampanti trovate</item>
+ <item quantity="one"><xliff:g id="COUNT_0">%1$s</xliff:g> stampante trovata</item>
</plurals>
<string name="printer_extended_description_template" msgid="1366699227703381874">"<xliff:g id="PRINT_SERVICE_LABEL">%1$s</xliff:g> - <xliff:g id="PRINTER_DESCRIPTION">%2$s</xliff:g>"</string>
<string name="printer_info_desc" msgid="7181988788991581654">"Ulteriori informazioni su questa stampante"</string>
@@ -76,8 +76,8 @@
<string name="disabled_services_title" msgid="7313253167968363211">"Servizi disattivati"</string>
<string name="all_services_title" msgid="5578662754874906455">"Tutti i servizi"</string>
<plurals name="print_services_recommendation_subtitle" formatted="false" msgid="5678487708807185138">
- <item quantity="one">Install to discover <xliff:g id="COUNT_1">%1$s</xliff:g> printers</item>
<item quantity="other">Installa per rilevare <xliff:g id="COUNT_1">%1$s</xliff:g> stampanti</item>
+ <item quantity="one">Installa per rilevare <xliff:g id="COUNT_0">%1$s</xliff:g> stampante</item>
</plurals>
<string name="printing_notification_title_template" msgid="295903957762447362">"Stampa di <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
<string name="cancelling_notification_title_template" msgid="1821759594704703197">"Annullamento di <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
diff --git a/packages/PrintSpooler/res/values-pt-rPT/strings.xml b/packages/PrintSpooler/res/values-pt-rPT/strings.xml
index 56001d8..4517efe 100644
--- a/packages/PrintSpooler/res/values-pt-rPT/strings.xml
+++ b/packages/PrintSpooler/res/values-pt-rPT/strings.xml
@@ -56,8 +56,8 @@
<string name="print_select_printer" msgid="7388760939873368698">"Selecionar impressora"</string>
<string name="print_forget_printer" msgid="5035287497291910766">"Esquecer impressora"</string>
<plurals name="print_search_result_count_utterance" formatted="false" msgid="6997663738361080868">
- <item quantity="one"><xliff:g id="COUNT_0">%1$s</xliff:g> impressora encontrada</item>
<item quantity="other"><xliff:g id="COUNT_1">%1$s</xliff:g> impressoras encontradas</item>
+ <item quantity="one"><xliff:g id="COUNT_0">%1$s</xliff:g> impressora encontrada</item>
</plurals>
<string name="printer_extended_description_template" msgid="1366699227703381874">"<xliff:g id="PRINT_SERVICE_LABEL">%1$s</xliff:g> – <xliff:g id="PRINTER_DESCRIPTION">%2$s</xliff:g>"</string>
<string name="printer_info_desc" msgid="7181988788991581654">"Mais informações acerca desta impressora"</string>
@@ -76,8 +76,8 @@
<string name="disabled_services_title" msgid="7313253167968363211">"Serviços desativados"</string>
<string name="all_services_title" msgid="5578662754874906455">"Todos os serviços"</string>
<plurals name="print_services_recommendation_subtitle" formatted="false" msgid="5678487708807185138">
- <item quantity="one">Instale para detetar <xliff:g id="COUNT_0">%1$s</xliff:g> impressora</item>
<item quantity="other">Instale para detetar <xliff:g id="COUNT_1">%1$s</xliff:g> impressoras</item>
+ <item quantity="one">Instale para detetar <xliff:g id="COUNT_0">%1$s</xliff:g> impressora</item>
</plurals>
<string name="printing_notification_title_template" msgid="295903957762447362">"A imprimir <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
<string name="cancelling_notification_title_template" msgid="1821759594704703197">"A cancelar <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
diff --git a/packages/SettingsLib/SearchWidget/res/values-or/strings.xml b/packages/SettingsLib/SearchWidget/res/values-or/strings.xml
index cf824de..322571ad 100644
--- a/packages/SettingsLib/SearchWidget/res/values-or/strings.xml
+++ b/packages/SettingsLib/SearchWidget/res/values-or/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="search_menu" msgid="1914043873178389845">"ସେଟିଂସ୍ ସନ୍ଧାନ କରନ୍ତୁ"</string>
+ <string name="search_menu" msgid="1914043873178389845">"ସେଟିଂସ ସନ୍ଧାନ କରନ୍ତୁ"</string>
</resources>
diff --git a/packages/SettingsLib/SettingsTheme/res/color-v31/settingslib_text_color_primary.xml b/packages/SettingsLib/SettingsTheme/res/color-v31/settingslib_text_color_primary.xml
new file mode 100644
index 0000000..221d2db
--- /dev/null
+++ b/packages/SettingsLib/SettingsTheme/res/color-v31/settingslib_text_color_primary.xml
@@ -0,0 +1,22 @@
+<?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.
+-->
+
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+ <item android:state_enabled="false"
+ android:alpha="?android:attr/disabledAlpha"
+ android:color="@color/settingslib_text_color_primary_device_default"/>
+ <item android:color="@color/settingslib_text_color_primary_device_default"/>
+</selector>
diff --git a/packages/SettingsLib/SettingsTheme/res/values-v31/styles.xml b/packages/SettingsLib/SettingsTheme/res/values-v31/styles.xml
index 9d39911..cba1a9c 100644
--- a/packages/SettingsLib/SettingsTheme/res/values-v31/styles.xml
+++ b/packages/SettingsLib/SettingsTheme/res/values-v31/styles.xml
@@ -17,7 +17,7 @@
<resources>
<style name="TextAppearance.PreferenceTitle.SettingsLib"
parent="@android:style/TextAppearance.Material.Subhead">
- <item name="android:textColor">@color/settingslib_text_color_primary_device_default</item>
+ <item name="android:textColor">@color/settingslib_text_color_primary</item>
<item name="android:fontFamily">@string/settingslib_config_headlineFontFamily</item>
<item name="android:textSize">20sp</item>
</style>
diff --git a/packages/SettingsLib/res/values-af/strings.xml b/packages/SettingsLib/res/values-af/strings.xml
index 24d1171..23f9a13 100644
--- a/packages/SettingsLib/res/values-af/strings.xml
+++ b/packages/SettingsLib/res/values-af/strings.xml
@@ -533,6 +533,8 @@
<string name="accessibility_manual_zen_less_time" msgid="6828877595848229965">"Minder tyd."</string>
<string name="cancel" msgid="5665114069455378395">"Kanselleer"</string>
<string name="okay" msgid="949938843324579502">"OK"</string>
+ <!-- no translation found for done (381184316122520313) -->
+ <skip />
<string name="alarms_and_reminders_label" msgid="6918395649731424294">"Wekkers en onthounotas"</string>
<string name="alarms_and_reminders_switch_title" msgid="4939393911531826222">"Laat toe dat wekkers en onthounotas gestel word"</string>
<string name="alarms_and_reminders_title" msgid="8819933264635406032">"Wekkers en onthounotas"</string>
@@ -551,7 +553,9 @@
<string name="zen_mode_duration_always_prompt_title" msgid="3212996860498119555">"Vra elke keer"</string>
<string name="zen_mode_forever" msgid="3339224497605461291">"Totdat jy dit afskakel"</string>
<string name="time_unit_just_now" msgid="3006134267292728099">"Sopas"</string>
- <string name="media_transfer_this_device_name" msgid="2357329267148436433">"Hierdie foon"</string>
+ <string name="media_transfer_this_device_name" product="default" msgid="2357329267148436433">"Hierdie foon"</string>
+ <!-- no translation found for media_transfer_this_device_name (3714653244000242800) -->
+ <skip />
<string name="media_transfer_this_phone" msgid="7194341457812151531">"Hierdie foon"</string>
<string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"Kan nie koppel nie. Skakel toestel af en weer aan"</string>
<string name="media_transfer_wired_device_name" msgid="4447880899964056007">"Bedrade oudiotoestel"</string>
@@ -591,7 +595,9 @@
<string name="user_set_lock_button" msgid="1427128184982594856">"Stel slot op"</string>
<string name="user_switch_to_user" msgid="6975428297154968543">"Skakel oor na <xliff:g id="USER_NAME">%s</xliff:g>"</string>
<string name="creating_new_user_dialog_message" msgid="7232880257538970375">"Skep tans nuwe gebruiker …"</string>
+ <string name="creating_new_guest_dialog_message" msgid="1114905602181350690">"Skep tans nuwe gas …"</string>
<string name="add_user_failed" msgid="4809887794313944872">"Kon nie \'n nuwe gebruiker skep nie"</string>
+ <string name="add_guest_failed" msgid="8074548434469843443">"Kon nie ’n nuwe gas skep nie"</string>
<string name="user_nickname" msgid="262624187455825083">"Bynaam"</string>
<string name="guest_new_guest" msgid="3482026122932643557">"Voeg gas by"</string>
<string name="guest_exit_guest" msgid="5908239569510734136">"Verwyder gas"</string>
@@ -644,4 +650,7 @@
<string name="dream_complication_title_cast_info" msgid="4038776652841885084">"Uitsaai-inligting"</string>
<string name="avatar_picker_title" msgid="8492884172713170652">"Kies \'n profielprent"</string>
<string name="default_user_icon_description" msgid="6554047177298972638">"Verstekgebruikerikoon"</string>
+ <string name="physical_keyboard_title" msgid="4811935435315835220">"Fisieke sleutelbord"</string>
+ <string name="keyboard_layout_dialog_title" msgid="3927180147005616290">"Kies sleutelborduitleg"</string>
+ <string name="keyboard_layout_default_label" msgid="1997292217218546957">"Verstek"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-am/strings.xml b/packages/SettingsLib/res/values-am/strings.xml
index e620141..c32e94f 100644
--- a/packages/SettingsLib/res/values-am/strings.xml
+++ b/packages/SettingsLib/res/values-am/strings.xml
@@ -533,6 +533,8 @@
<string name="accessibility_manual_zen_less_time" msgid="6828877595848229965">"ያነሰ ጊዜ።"</string>
<string name="cancel" msgid="5665114069455378395">"ይቅር"</string>
<string name="okay" msgid="949938843324579502">"እሺ"</string>
+ <!-- no translation found for done (381184316122520313) -->
+ <skip />
<string name="alarms_and_reminders_label" msgid="6918395649731424294">"ማንቂያዎች እና አስታዋሾች"</string>
<string name="alarms_and_reminders_switch_title" msgid="4939393911531826222">"ማንቂያዎች እና አስታዋሾች እንዲዋቀሩ ይፍቀዱ"</string>
<string name="alarms_and_reminders_title" msgid="8819933264635406032">"ማንቂያዎች እና አስታዋሾች"</string>
@@ -551,7 +553,9 @@
<string name="zen_mode_duration_always_prompt_title" msgid="3212996860498119555">"ሁልጊዜ ጠይቅ"</string>
<string name="zen_mode_forever" msgid="3339224497605461291">"እስኪያጠፉት ድረስ"</string>
<string name="time_unit_just_now" msgid="3006134267292728099">"ልክ አሁን"</string>
- <string name="media_transfer_this_device_name" msgid="2357329267148436433">"ይህ ስልክ"</string>
+ <string name="media_transfer_this_device_name" product="default" msgid="2357329267148436433">"ይህ ስልክ"</string>
+ <!-- no translation found for media_transfer_this_device_name (3714653244000242800) -->
+ <skip />
<string name="media_transfer_this_phone" msgid="7194341457812151531">"ይህ ስልክ"</string>
<string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"መገናኘት ላይ ችግር። መሳሪያውን ያጥፉት እና እንደገና ያብሩት"</string>
<string name="media_transfer_wired_device_name" msgid="4447880899964056007">"ባለገመድ የኦዲዮ መሣሪያ"</string>
@@ -591,7 +595,9 @@
<string name="user_set_lock_button" msgid="1427128184982594856">"ቁልፍ አዘጋጅ"</string>
<string name="user_switch_to_user" msgid="6975428297154968543">"ወደ <xliff:g id="USER_NAME">%s</xliff:g> ቀይር"</string>
<string name="creating_new_user_dialog_message" msgid="7232880257538970375">"አዲስ ተጠቃሚ በመፍጠር ላይ…"</string>
+ <string name="creating_new_guest_dialog_message" msgid="1114905602181350690">"አዲስ እንግዳ በመፍጠር ላይ…"</string>
<string name="add_user_failed" msgid="4809887794313944872">"አዲስ ተጠቃሚን መፍጠር አልተሳካም"</string>
+ <string name="add_guest_failed" msgid="8074548434469843443">"አዲስ እንግዳ መፍጠር አልተሳካም"</string>
<string name="user_nickname" msgid="262624187455825083">"ቅጽል ስም"</string>
<string name="guest_new_guest" msgid="3482026122932643557">"እንግዳን አክል"</string>
<string name="guest_exit_guest" msgid="5908239569510734136">"እንግዳን አስወግድ"</string>
@@ -644,4 +650,7 @@
<string name="dream_complication_title_cast_info" msgid="4038776652841885084">"የCast መረጃ"</string>
<string name="avatar_picker_title" msgid="8492884172713170652">"የመገለጫ ሥዕል ይምረጡ"</string>
<string name="default_user_icon_description" msgid="6554047177298972638">"ነባሪ የተጠቃሚ አዶ"</string>
+ <string name="physical_keyboard_title" msgid="4811935435315835220">"አካላዊ ቁልፍ ሰሌዳ"</string>
+ <string name="keyboard_layout_dialog_title" msgid="3927180147005616290">"የቁልፍ ሰሌዳ አቀማመጥን ይምረጡ"</string>
+ <string name="keyboard_layout_default_label" msgid="1997292217218546957">"ነባሪ"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-ar/strings.xml b/packages/SettingsLib/res/values-ar/strings.xml
index 65e37e8..894bc3f 100644
--- a/packages/SettingsLib/res/values-ar/strings.xml
+++ b/packages/SettingsLib/res/values-ar/strings.xml
@@ -533,6 +533,8 @@
<string name="accessibility_manual_zen_less_time" msgid="6828877595848229965">"وقت أقل."</string>
<string name="cancel" msgid="5665114069455378395">"إلغاء"</string>
<string name="okay" msgid="949938843324579502">"حسنًا"</string>
+ <!-- no translation found for done (381184316122520313) -->
+ <skip />
<string name="alarms_and_reminders_label" msgid="6918395649731424294">"المنبّهات والتذكيرات"</string>
<string name="alarms_and_reminders_switch_title" msgid="4939393911531826222">"السماح بضبط المنبّهات والتذكيرات"</string>
<string name="alarms_and_reminders_title" msgid="8819933264635406032">"المنبّهات والتذكيرات"</string>
@@ -551,7 +553,9 @@
<string name="zen_mode_duration_always_prompt_title" msgid="3212996860498119555">"السؤال في كل مرة"</string>
<string name="zen_mode_forever" msgid="3339224497605461291">"إلى أن يتم إيقاف الوضع"</string>
<string name="time_unit_just_now" msgid="3006134267292728099">"للتو"</string>
- <string name="media_transfer_this_device_name" msgid="2357329267148436433">"هذا الهاتف"</string>
+ <string name="media_transfer_this_device_name" product="default" msgid="2357329267148436433">"هذا الهاتف"</string>
+ <!-- no translation found for media_transfer_this_device_name (3714653244000242800) -->
+ <skip />
<string name="media_transfer_this_phone" msgid="7194341457812151531">"هذا الهاتف"</string>
<string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"حدثت مشكلة أثناء الاتصال. يُرجى إيقاف الجهاز ثم إعادة تشغيله."</string>
<string name="media_transfer_wired_device_name" msgid="4447880899964056007">"جهاز سماعي سلكي"</string>
@@ -591,7 +595,9 @@
<string name="user_set_lock_button" msgid="1427128184982594856">"تعيين التأمين"</string>
<string name="user_switch_to_user" msgid="6975428297154968543">"التبديل إلى <xliff:g id="USER_NAME">%s</xliff:g>"</string>
<string name="creating_new_user_dialog_message" msgid="7232880257538970375">"جارٍ إنشاء مستخدم جديد…"</string>
+ <string name="creating_new_guest_dialog_message" msgid="1114905602181350690">"جارٍ إنشاء جلسة ضيف جديدة…"</string>
<string name="add_user_failed" msgid="4809887794313944872">"تعذّر إنشاء مستخدم جديد."</string>
+ <string name="add_guest_failed" msgid="8074548434469843443">"تعذّر إنشاء جلسة ضيف جديدة."</string>
<string name="user_nickname" msgid="262624187455825083">"اللقب"</string>
<string name="guest_new_guest" msgid="3482026122932643557">"إضافة ضيف"</string>
<string name="guest_exit_guest" msgid="5908239569510734136">"إزالة جلسة الضيف"</string>
@@ -644,4 +650,10 @@
<string name="dream_complication_title_cast_info" msgid="4038776652841885084">"معلومات البث"</string>
<string name="avatar_picker_title" msgid="8492884172713170652">"اختيار صورة الملف الشخصي"</string>
<string name="default_user_icon_description" msgid="6554047177298972638">"رمز المستخدم التلقائي"</string>
+ <!-- no translation found for physical_keyboard_title (4811935435315835220) -->
+ <skip />
+ <!-- no translation found for keyboard_layout_dialog_title (3927180147005616290) -->
+ <skip />
+ <!-- no translation found for keyboard_layout_default_label (1997292217218546957) -->
+ <skip />
</resources>
diff --git a/packages/SettingsLib/res/values-as/strings.xml b/packages/SettingsLib/res/values-as/strings.xml
index f965a34..4ed2e38 100644
--- a/packages/SettingsLib/res/values-as/strings.xml
+++ b/packages/SettingsLib/res/values-as/strings.xml
@@ -533,6 +533,8 @@
<string name="accessibility_manual_zen_less_time" msgid="6828877595848229965">"কম সময়।"</string>
<string name="cancel" msgid="5665114069455378395">"বাতিল কৰক"</string>
<string name="okay" msgid="949938843324579502">"ঠিক"</string>
+ <!-- no translation found for done (381184316122520313) -->
+ <skip />
<string name="alarms_and_reminders_label" msgid="6918395649731424294">"এলাৰ্ম আৰু ৰিমাইণ্ডাৰ"</string>
<string name="alarms_and_reminders_switch_title" msgid="4939393911531826222">"এলাৰ্ম আৰু ৰিমাইণ্ডাৰ ছেট কৰাৰ অনুমতি দিয়ক"</string>
<string name="alarms_and_reminders_title" msgid="8819933264635406032">"এলাৰ্ম আৰু ৰিমাইণ্ডাৰ"</string>
@@ -551,7 +553,9 @@
<string name="zen_mode_duration_always_prompt_title" msgid="3212996860498119555">"প্ৰতিবাৰতে সোধক"</string>
<string name="zen_mode_forever" msgid="3339224497605461291">"আপুনি অফ নকৰা পর্যন্ত"</string>
<string name="time_unit_just_now" msgid="3006134267292728099">"এই মাত্ৰ"</string>
- <string name="media_transfer_this_device_name" msgid="2357329267148436433">"এই ফ’নটো"</string>
+ <string name="media_transfer_this_device_name" product="default" msgid="2357329267148436433">"এই ফ’নটো"</string>
+ <!-- no translation found for media_transfer_this_device_name (3714653244000242800) -->
+ <skip />
<string name="media_transfer_this_phone" msgid="7194341457812151531">"এই ফ’নটো"</string>
<string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"সংযোগ হোৱাত সমস্যা হৈছে। ডিভাইচটো অফ কৰি পুনৰ অন কৰক"</string>
<string name="media_transfer_wired_device_name" msgid="4447880899964056007">"তাঁৰযুক্ত অডিঅ’ ডিভাইচ"</string>
@@ -591,7 +595,9 @@
<string name="user_set_lock_button" msgid="1427128184982594856">"লক ছেট কৰক"</string>
<string name="user_switch_to_user" msgid="6975428297154968543">"<xliff:g id="USER_NAME">%s</xliff:g>লৈ সলনি কৰক"</string>
<string name="creating_new_user_dialog_message" msgid="7232880257538970375">"নতুন ব্যৱহাৰকাৰী সৃষ্টি কৰি থকা হৈছে…"</string>
+ <string name="creating_new_guest_dialog_message" msgid="1114905602181350690">"নতুন অতিথি সৃষ্টি কৰি থকা হৈছে…"</string>
<string name="add_user_failed" msgid="4809887794313944872">"নতুন ব্যৱহাৰকাৰী সৃষ্টি কৰিব পৰা নগ’ল"</string>
+ <string name="add_guest_failed" msgid="8074548434469843443">"নতুন অতিথি সৃষ্টি কৰিব পৰা নগ’ল"</string>
<string name="user_nickname" msgid="262624187455825083">"উপনাম"</string>
<string name="guest_new_guest" msgid="3482026122932643557">"অতিথি যোগ কৰক"</string>
<string name="guest_exit_guest" msgid="5908239569510734136">"অতিথি আঁতৰাওক"</string>
@@ -644,4 +650,7 @@
<string name="dream_complication_title_cast_info" msgid="4038776652841885084">"কাষ্টৰ তথ্য"</string>
<string name="avatar_picker_title" msgid="8492884172713170652">"এখন প্ৰ’ফাইল চিত্ৰ বাছনি কৰক"</string>
<string name="default_user_icon_description" msgid="6554047177298972638">"ডিফ’ল্ট ব্যৱহাৰকাৰীৰ চিহ্ন"</string>
+ <string name="physical_keyboard_title" msgid="4811935435315835220">"কায়িক কীব’ৰ্ড"</string>
+ <string name="keyboard_layout_dialog_title" msgid="3927180147005616290">"কীব\'ৰ্ডৰ চানেকি বাছক"</string>
+ <string name="keyboard_layout_default_label" msgid="1997292217218546957">"ডিফ’ল্ট"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-az/strings.xml b/packages/SettingsLib/res/values-az/strings.xml
index 3fb3f2c..4b2fa6c 100644
--- a/packages/SettingsLib/res/values-az/strings.xml
+++ b/packages/SettingsLib/res/values-az/strings.xml
@@ -533,6 +533,8 @@
<string name="accessibility_manual_zen_less_time" msgid="6828877595848229965">"Daha az vaxt."</string>
<string name="cancel" msgid="5665114069455378395">"Ləğv edin"</string>
<string name="okay" msgid="949938843324579502">"Ok"</string>
+ <!-- no translation found for done (381184316122520313) -->
+ <skip />
<string name="alarms_and_reminders_label" msgid="6918395649731424294">"Siqnallar və xatırladıcılar"</string>
<string name="alarms_and_reminders_switch_title" msgid="4939393911531826222">"Siqnallar və xatırlatmaları ayarlamağa icazə verin"</string>
<string name="alarms_and_reminders_title" msgid="8819933264635406032">"Siqnallar və xatırlatmalar"</string>
@@ -551,7 +553,9 @@
<string name="zen_mode_duration_always_prompt_title" msgid="3212996860498119555">"Həmişə soruşulsun"</string>
<string name="zen_mode_forever" msgid="3339224497605461291">"Deaktiv edilənə qədər"</string>
<string name="time_unit_just_now" msgid="3006134267292728099">"İndicə"</string>
- <string name="media_transfer_this_device_name" msgid="2357329267148436433">"Bu telefon"</string>
+ <string name="media_transfer_this_device_name" product="default" msgid="2357329267148436433">"Bu telefon"</string>
+ <!-- no translation found for media_transfer_this_device_name (3714653244000242800) -->
+ <skip />
<string name="media_transfer_this_phone" msgid="7194341457812151531">"Bu telefon"</string>
<string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"Qoşulmaqla bağlı problem. Cihazı deaktiv edin, sonra yenidən aktiv edin"</string>
<string name="media_transfer_wired_device_name" msgid="4447880899964056007">"Simli audio cihaz"</string>
@@ -591,7 +595,9 @@
<string name="user_set_lock_button" msgid="1427128184982594856">"Kilid ayarlayın"</string>
<string name="user_switch_to_user" msgid="6975428297154968543">"<xliff:g id="USER_NAME">%s</xliff:g> adlı istifadəçiyə keçin"</string>
<string name="creating_new_user_dialog_message" msgid="7232880257538970375">"Yeni istifadəçi yaradılır…"</string>
+ <string name="creating_new_guest_dialog_message" msgid="1114905602181350690">"Yeni qonaq yaradılır…"</string>
<string name="add_user_failed" msgid="4809887794313944872">"Yeni istifadəçi yaratmaq alınmadı"</string>
+ <string name="add_guest_failed" msgid="8074548434469843443">"Yeni qonaq yaratmaq alınmadı"</string>
<string name="user_nickname" msgid="262624187455825083">"Ləqəb"</string>
<string name="guest_new_guest" msgid="3482026122932643557">"Qonaq əlavə edin"</string>
<string name="guest_exit_guest" msgid="5908239569510734136">"Qonağı silin"</string>
@@ -644,4 +650,7 @@
<string name="dream_complication_title_cast_info" msgid="4038776652841885084">"Yayım məlumatı"</string>
<string name="avatar_picker_title" msgid="8492884172713170652">"Profil şəkli seçin"</string>
<string name="default_user_icon_description" msgid="6554047177298972638">"Defolt istifadəçi ikonası"</string>
+ <string name="physical_keyboard_title" msgid="4811935435315835220">"Fiziki klaviatura"</string>
+ <string name="keyboard_layout_dialog_title" msgid="3927180147005616290">"Klaviatura düzənini seçin"</string>
+ <string name="keyboard_layout_default_label" msgid="1997292217218546957">"Defolt"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-b+sr+Latn/strings.xml b/packages/SettingsLib/res/values-b+sr+Latn/strings.xml
index a267b46..ffc38bf 100644
--- a/packages/SettingsLib/res/values-b+sr+Latn/strings.xml
+++ b/packages/SettingsLib/res/values-b+sr+Latn/strings.xml
@@ -533,6 +533,8 @@
<string name="accessibility_manual_zen_less_time" msgid="6828877595848229965">"Manje vremena."</string>
<string name="cancel" msgid="5665114069455378395">"Otkaži"</string>
<string name="okay" msgid="949938843324579502">"Potvrdi"</string>
+ <!-- no translation found for done (381184316122520313) -->
+ <skip />
<string name="alarms_and_reminders_label" msgid="6918395649731424294">"Alarmi i podsetnici"</string>
<string name="alarms_and_reminders_switch_title" msgid="4939393911531826222">"Omogući podešavanje alarma i podsetnika"</string>
<string name="alarms_and_reminders_title" msgid="8819933264635406032">"Alarmi i podsetnici"</string>
@@ -551,7 +553,9 @@
<string name="zen_mode_duration_always_prompt_title" msgid="3212996860498119555">"Pitaj svaki put"</string>
<string name="zen_mode_forever" msgid="3339224497605461291">"Dok ne isključite"</string>
<string name="time_unit_just_now" msgid="3006134267292728099">"Upravo"</string>
- <string name="media_transfer_this_device_name" msgid="2357329267148436433">"Ovaj telefon"</string>
+ <string name="media_transfer_this_device_name" product="default" msgid="2357329267148436433">"Ovaj telefon"</string>
+ <!-- no translation found for media_transfer_this_device_name (3714653244000242800) -->
+ <skip />
<string name="media_transfer_this_phone" msgid="7194341457812151531">"Ovaj telefon"</string>
<string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"Problem pri povezivanju. Isključite uređaj, pa ga ponovo uključite"</string>
<string name="media_transfer_wired_device_name" msgid="4447880899964056007">"Žičani audio uređaj"</string>
@@ -591,7 +595,9 @@
<string name="user_set_lock_button" msgid="1427128184982594856">"Podesi zaključavanje"</string>
<string name="user_switch_to_user" msgid="6975428297154968543">"Pređi na korisnika <xliff:g id="USER_NAME">%s</xliff:g>"</string>
<string name="creating_new_user_dialog_message" msgid="7232880257538970375">"Pravi se novi korisnik…"</string>
+ <string name="creating_new_guest_dialog_message" msgid="1114905602181350690">"Pravi se novi gost…"</string>
<string name="add_user_failed" msgid="4809887794313944872">"Pravljenje novog korisnika nije uspelo"</string>
+ <string name="add_guest_failed" msgid="8074548434469843443">"Pravljenje novog gosta nije uspelo"</string>
<string name="user_nickname" msgid="262624187455825083">"Nadimak"</string>
<string name="guest_new_guest" msgid="3482026122932643557">"Dodaj gosta"</string>
<string name="guest_exit_guest" msgid="5908239569510734136">"Ukloni gosta"</string>
@@ -644,4 +650,7 @@
<string name="dream_complication_title_cast_info" msgid="4038776652841885084">"Podaci o prebacivanju"</string>
<string name="avatar_picker_title" msgid="8492884172713170652">"Odaberite sliku profila"</string>
<string name="default_user_icon_description" msgid="6554047177298972638">"Podrazumevana ikona korisnika"</string>
+ <string name="physical_keyboard_title" msgid="4811935435315835220">"Fizička tastatura"</string>
+ <string name="keyboard_layout_dialog_title" msgid="3927180147005616290">"Odaberite raspored tastature"</string>
+ <string name="keyboard_layout_default_label" msgid="1997292217218546957">"Podrazumevano"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-be/strings.xml b/packages/SettingsLib/res/values-be/strings.xml
index 4a1f387..ddadbea 100644
--- a/packages/SettingsLib/res/values-be/strings.xml
+++ b/packages/SettingsLib/res/values-be/strings.xml
@@ -533,6 +533,8 @@
<string name="accessibility_manual_zen_less_time" msgid="6828877595848229965">"Менш часу."</string>
<string name="cancel" msgid="5665114069455378395">"Скасаваць"</string>
<string name="okay" msgid="949938843324579502">"ОК"</string>
+ <!-- no translation found for done (381184316122520313) -->
+ <skip />
<string name="alarms_and_reminders_label" msgid="6918395649731424294">"Будзільнікі і напаміны"</string>
<string name="alarms_and_reminders_switch_title" msgid="4939393911531826222">"Дазволіць усталёўваць будзільнікі і напаміны"</string>
<string name="alarms_and_reminders_title" msgid="8819933264635406032">"Будзільнікі і напаміны"</string>
@@ -551,7 +553,9 @@
<string name="zen_mode_duration_always_prompt_title" msgid="3212996860498119555">"Заўсёды пытацца"</string>
<string name="zen_mode_forever" msgid="3339224497605461291">"Пакуль не выключыце"</string>
<string name="time_unit_just_now" msgid="3006134267292728099">"Толькі што"</string>
- <string name="media_transfer_this_device_name" msgid="2357329267148436433">"Гэты тэлефон"</string>
+ <string name="media_transfer_this_device_name" product="default" msgid="2357329267148436433">"Гэты тэлефон"</string>
+ <!-- no translation found for media_transfer_this_device_name (3714653244000242800) -->
+ <skip />
<string name="media_transfer_this_phone" msgid="7194341457812151531">"Гэты тэлефон"</string>
<string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"Праблема з падключэннем. Выключыце і зноў уключыце прыладу"</string>
<string name="media_transfer_wired_device_name" msgid="4447880899964056007">"Правадная аўдыяпрылада"</string>
@@ -591,7 +595,9 @@
<string name="user_set_lock_button" msgid="1427128184982594856">"Усталёўка блакiроўкi"</string>
<string name="user_switch_to_user" msgid="6975428297154968543">"Пераключыцца на карыстальніка <xliff:g id="USER_NAME">%s</xliff:g>"</string>
<string name="creating_new_user_dialog_message" msgid="7232880257538970375">"Ствараецца новы карыстальнік…"</string>
+ <string name="creating_new_guest_dialog_message" msgid="1114905602181350690">"Ствараецца новы госць…"</string>
<string name="add_user_failed" msgid="4809887794313944872">"Не ўдалося стварыць новага карыстальніка"</string>
+ <string name="add_guest_failed" msgid="8074548434469843443">"Не ўдалося стварыць новага госця"</string>
<string name="user_nickname" msgid="262624187455825083">"Псеўданім"</string>
<string name="guest_new_guest" msgid="3482026122932643557">"Дадаць госця"</string>
<string name="guest_exit_guest" msgid="5908239569510734136">"Выдаліць госця"</string>
@@ -644,4 +650,10 @@
<string name="dream_complication_title_cast_info" msgid="4038776652841885084">"Даныя пра трансляцыю"</string>
<string name="avatar_picker_title" msgid="8492884172713170652">"Выберыце відарыс профілю"</string>
<string name="default_user_icon_description" msgid="6554047177298972638">"Стандартны карыстальніцкі значок"</string>
+ <!-- no translation found for physical_keyboard_title (4811935435315835220) -->
+ <skip />
+ <!-- no translation found for keyboard_layout_dialog_title (3927180147005616290) -->
+ <skip />
+ <!-- no translation found for keyboard_layout_default_label (1997292217218546957) -->
+ <skip />
</resources>
diff --git a/packages/SettingsLib/res/values-bg/strings.xml b/packages/SettingsLib/res/values-bg/strings.xml
index c3fd060..42f8782 100644
--- a/packages/SettingsLib/res/values-bg/strings.xml
+++ b/packages/SettingsLib/res/values-bg/strings.xml
@@ -533,6 +533,8 @@
<string name="accessibility_manual_zen_less_time" msgid="6828877595848229965">"По-малко време."</string>
<string name="cancel" msgid="5665114069455378395">"Отказ"</string>
<string name="okay" msgid="949938843324579502">"ОK"</string>
+ <!-- no translation found for done (381184316122520313) -->
+ <skip />
<string name="alarms_and_reminders_label" msgid="6918395649731424294">"Будилници и напомняния"</string>
<string name="alarms_and_reminders_switch_title" msgid="4939393911531826222">"Разреш. на задаването на будилници и напомняния"</string>
<string name="alarms_and_reminders_title" msgid="8819933264635406032">"Будилници и напомняния"</string>
@@ -551,7 +553,9 @@
<string name="zen_mode_duration_always_prompt_title" msgid="3212996860498119555">"Да се пита винаги"</string>
<string name="zen_mode_forever" msgid="3339224497605461291">"До изключване"</string>
<string name="time_unit_just_now" msgid="3006134267292728099">"Току-що"</string>
- <string name="media_transfer_this_device_name" msgid="2357329267148436433">"Този телефон"</string>
+ <string name="media_transfer_this_device_name" product="default" msgid="2357329267148436433">"Този телефон"</string>
+ <!-- no translation found for media_transfer_this_device_name (3714653244000242800) -->
+ <skip />
<string name="media_transfer_this_phone" msgid="7194341457812151531">"Този телефон"</string>
<string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"При свързването възникна проблем. Изключете устройството и го включете отново"</string>
<string name="media_transfer_wired_device_name" msgid="4447880899964056007">"Аудиоустройство с кабел"</string>
@@ -591,7 +595,9 @@
<string name="user_set_lock_button" msgid="1427128184982594856">"Задаване на заключване"</string>
<string name="user_switch_to_user" msgid="6975428297154968543">"Превключване към: <xliff:g id="USER_NAME">%s</xliff:g>"</string>
<string name="creating_new_user_dialog_message" msgid="7232880257538970375">"Създава се нов потребител…"</string>
+ <string name="creating_new_guest_dialog_message" msgid="1114905602181350690">"Новият гост се създава…"</string>
<string name="add_user_failed" msgid="4809887794313944872">"Неуспешно създаване на нов потребител"</string>
+ <string name="add_guest_failed" msgid="8074548434469843443">"Създаването на нов гост не бе успешно"</string>
<string name="user_nickname" msgid="262624187455825083">"Псевдоним"</string>
<string name="guest_new_guest" msgid="3482026122932643557">"Добавяне на гост"</string>
<string name="guest_exit_guest" msgid="5908239569510734136">"Премахване на госта"</string>
@@ -644,4 +650,7 @@
<string name="dream_complication_title_cast_info" msgid="4038776652841885084">"Предаване: Инф."</string>
<string name="avatar_picker_title" msgid="8492884172713170652">"Изберете снимка на потребителския профил"</string>
<string name="default_user_icon_description" msgid="6554047177298972638">"Икона за основния потребител"</string>
+ <string name="physical_keyboard_title" msgid="4811935435315835220">"Физическа клавиатура"</string>
+ <string name="keyboard_layout_dialog_title" msgid="3927180147005616290">"Избор на клавиатурна подредба"</string>
+ <string name="keyboard_layout_default_label" msgid="1997292217218546957">"По подразбиране"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-bn/strings.xml b/packages/SettingsLib/res/values-bn/strings.xml
index 2e9360e..d21cfad 100644
--- a/packages/SettingsLib/res/values-bn/strings.xml
+++ b/packages/SettingsLib/res/values-bn/strings.xml
@@ -533,6 +533,8 @@
<string name="accessibility_manual_zen_less_time" msgid="6828877595848229965">"আরও কম।"</string>
<string name="cancel" msgid="5665114069455378395">"বাতিল"</string>
<string name="okay" msgid="949938843324579502">"ঠিক আছে"</string>
+ <!-- no translation found for done (381184316122520313) -->
+ <skip />
<string name="alarms_and_reminders_label" msgid="6918395649731424294">"অ্যালার্ম এবং রিমাইন্ডার"</string>
<string name="alarms_and_reminders_switch_title" msgid="4939393911531826222">"অ্যালার্ম এবং রিমাইন্ডার সেট করার অনুমতি দিন"</string>
<string name="alarms_and_reminders_title" msgid="8819933264635406032">"অ্যালার্ম এবং রিমাইন্ডার"</string>
@@ -551,7 +553,9 @@
<string name="zen_mode_duration_always_prompt_title" msgid="3212996860498119555">"প্রতিবার জিজ্ঞেস করা হবে"</string>
<string name="zen_mode_forever" msgid="3339224497605461291">"যতক্ষণ না আপনি বন্ধ করছেন"</string>
<string name="time_unit_just_now" msgid="3006134267292728099">"এখনই"</string>
- <string name="media_transfer_this_device_name" msgid="2357329267148436433">"এই ফোন"</string>
+ <string name="media_transfer_this_device_name" product="default" msgid="2357329267148436433">"এই ফোন"</string>
+ <!-- no translation found for media_transfer_this_device_name (3714653244000242800) -->
+ <skip />
<string name="media_transfer_this_phone" msgid="7194341457812151531">"এই ফোনটি"</string>
<string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"কানেক্ট করতে সমস্যা হচ্ছে। ডিভাইস বন্ধ করে আবার চালু করুন"</string>
<string name="media_transfer_wired_device_name" msgid="4447880899964056007">"ওয়্যার অডিও ডিভাইস"</string>
@@ -591,7 +595,9 @@
<string name="user_set_lock_button" msgid="1427128184982594856">"লক সেট করুন"</string>
<string name="user_switch_to_user" msgid="6975428297154968543">"<xliff:g id="USER_NAME">%s</xliff:g>-এ পাল্টান"</string>
<string name="creating_new_user_dialog_message" msgid="7232880257538970375">"নতুন ব্যবহারকারী তৈরি করা হচ্ছে…"</string>
+ <string name="creating_new_guest_dialog_message" msgid="1114905602181350690">"নতুন অতিথি তৈরি করা হচ্ছে…"</string>
<string name="add_user_failed" msgid="4809887794313944872">"নতুন ব্যবহারকারী যোগ করা যায়নি"</string>
+ <string name="add_guest_failed" msgid="8074548434469843443">"নতুন অতিথি তৈরি করা যায়নি"</string>
<string name="user_nickname" msgid="262624187455825083">"বিশেষ নাম"</string>
<string name="guest_new_guest" msgid="3482026122932643557">"অতিথি যোগ করুন"</string>
<string name="guest_exit_guest" msgid="5908239569510734136">"অতিথি সরান"</string>
@@ -644,4 +650,10 @@
<string name="dream_complication_title_cast_info" msgid="4038776652841885084">"কাস্ট সম্পর্কিত তথ্য"</string>
<string name="avatar_picker_title" msgid="8492884172713170652">"একটি প্রোফাইল ছবি বেছে নিন"</string>
<string name="default_user_icon_description" msgid="6554047177298972638">"ডিফল্ট ব্যবহারকারীর আইকন"</string>
+ <!-- no translation found for physical_keyboard_title (4811935435315835220) -->
+ <skip />
+ <!-- no translation found for keyboard_layout_dialog_title (3927180147005616290) -->
+ <skip />
+ <!-- no translation found for keyboard_layout_default_label (1997292217218546957) -->
+ <skip />
</resources>
diff --git a/packages/SettingsLib/res/values-bs/strings.xml b/packages/SettingsLib/res/values-bs/strings.xml
index 77711cc..c17532b 100644
--- a/packages/SettingsLib/res/values-bs/strings.xml
+++ b/packages/SettingsLib/res/values-bs/strings.xml
@@ -533,6 +533,8 @@
<string name="accessibility_manual_zen_less_time" msgid="6828877595848229965">"Manje vremena."</string>
<string name="cancel" msgid="5665114069455378395">"Otkaži"</string>
<string name="okay" msgid="949938843324579502">"Uredu"</string>
+ <!-- no translation found for done (381184316122520313) -->
+ <skip />
<string name="alarms_and_reminders_label" msgid="6918395649731424294">"Alarmi i podsjetnici"</string>
<string name="alarms_and_reminders_switch_title" msgid="4939393911531826222">"Dozvoli postavljanje alarma i podsjetnika"</string>
<string name="alarms_and_reminders_title" msgid="8819933264635406032">"Alarmi i podsjetnici"</string>
@@ -551,7 +553,9 @@
<string name="zen_mode_duration_always_prompt_title" msgid="3212996860498119555">"Pitaj svaki put"</string>
<string name="zen_mode_forever" msgid="3339224497605461291">"Dok ne isključite"</string>
<string name="time_unit_just_now" msgid="3006134267292728099">"Upravo"</string>
- <string name="media_transfer_this_device_name" msgid="2357329267148436433">"Ovaj telefon"</string>
+ <string name="media_transfer_this_device_name" product="default" msgid="2357329267148436433">"Ovaj telefon"</string>
+ <!-- no translation found for media_transfer_this_device_name (3714653244000242800) -->
+ <skip />
<string name="media_transfer_this_phone" msgid="7194341457812151531">"Ovaj telefon"</string>
<string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"Došlo je do problema prilikom povezivanja. Isključite, pa ponovo uključite uređaj"</string>
<string name="media_transfer_wired_device_name" msgid="4447880899964056007">"Žičani audio uređaj"</string>
@@ -591,7 +595,9 @@
<string name="user_set_lock_button" msgid="1427128184982594856">"Postaviti zaključavanje"</string>
<string name="user_switch_to_user" msgid="6975428297154968543">"Prebaci na korisnika <xliff:g id="USER_NAME">%s</xliff:g>"</string>
<string name="creating_new_user_dialog_message" msgid="7232880257538970375">"Kreiranje novog korisnika…"</string>
+ <string name="creating_new_guest_dialog_message" msgid="1114905602181350690">"Kreiranje novog gosta…"</string>
<string name="add_user_failed" msgid="4809887794313944872">"Kreiranje novog korisnika nije uspjelo"</string>
+ <string name="add_guest_failed" msgid="8074548434469843443">"Kreiranje novog gosta nije uspjelo"</string>
<string name="user_nickname" msgid="262624187455825083">"Nadimak"</string>
<string name="guest_new_guest" msgid="3482026122932643557">"Dodaj gosta"</string>
<string name="guest_exit_guest" msgid="5908239569510734136">"Ukloni gosta"</string>
@@ -644,4 +650,7 @@
<string name="dream_complication_title_cast_info" msgid="4038776652841885084">"Podaci o emitiranju"</string>
<string name="avatar_picker_title" msgid="8492884172713170652">"Odaberite sliku profila"</string>
<string name="default_user_icon_description" msgid="6554047177298972638">"Zadana ikona korisnika"</string>
+ <string name="physical_keyboard_title" msgid="4811935435315835220">"Fizička tastatura"</string>
+ <string name="keyboard_layout_dialog_title" msgid="3927180147005616290">"Odaberite raspored tastature"</string>
+ <string name="keyboard_layout_default_label" msgid="1997292217218546957">"Zadano"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-ca/strings.xml b/packages/SettingsLib/res/values-ca/strings.xml
index 92e7c1a..c7f9ce6 100644
--- a/packages/SettingsLib/res/values-ca/strings.xml
+++ b/packages/SettingsLib/res/values-ca/strings.xml
@@ -533,6 +533,8 @@
<string name="accessibility_manual_zen_less_time" msgid="6828877595848229965">"Menys temps"</string>
<string name="cancel" msgid="5665114069455378395">"Cancel·la"</string>
<string name="okay" msgid="949938843324579502">"D\'acord"</string>
+ <!-- no translation found for done (381184316122520313) -->
+ <skip />
<string name="alarms_and_reminders_label" msgid="6918395649731424294">"Alarmes i recordatoris"</string>
<string name="alarms_and_reminders_switch_title" msgid="4939393911531826222">"Permet la configuració d\'alarmes i recordatoris"</string>
<string name="alarms_and_reminders_title" msgid="8819933264635406032">"Alarmes i recordatoris"</string>
@@ -551,7 +553,9 @@
<string name="zen_mode_duration_always_prompt_title" msgid="3212996860498119555">"Pregunta sempre"</string>
<string name="zen_mode_forever" msgid="3339224497605461291">"Fins que no el desactivis"</string>
<string name="time_unit_just_now" msgid="3006134267292728099">"Ara mateix"</string>
- <string name="media_transfer_this_device_name" msgid="2357329267148436433">"Aquest telèfon"</string>
+ <string name="media_transfer_this_device_name" product="default" msgid="2357329267148436433">"Aquest telèfon"</string>
+ <!-- no translation found for media_transfer_this_device_name (3714653244000242800) -->
+ <skip />
<string name="media_transfer_this_phone" msgid="7194341457812151531">"Aquest telèfon"</string>
<string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"Hi ha hagut un problema amb la connexió. Apaga el dispositiu i torna\'l a encendre."</string>
<string name="media_transfer_wired_device_name" msgid="4447880899964056007">"Dispositiu d\'àudio amb cable"</string>
@@ -591,7 +595,9 @@
<string name="user_set_lock_button" msgid="1427128184982594856">"Defineix un bloqueig"</string>
<string name="user_switch_to_user" msgid="6975428297154968543">"Canvia a <xliff:g id="USER_NAME">%s</xliff:g>"</string>
<string name="creating_new_user_dialog_message" msgid="7232880257538970375">"S\'està creant l\'usuari…"</string>
+ <string name="creating_new_guest_dialog_message" msgid="1114905602181350690">"S\'està creant un convidat…"</string>
<string name="add_user_failed" msgid="4809887794313944872">"No s\'ha pogut crear l\'usuari"</string>
+ <string name="add_guest_failed" msgid="8074548434469843443">"No s\'ha pogut crear un convidat"</string>
<string name="user_nickname" msgid="262624187455825083">"Àlies"</string>
<string name="guest_new_guest" msgid="3482026122932643557">"Afegeix un convidat"</string>
<string name="guest_exit_guest" msgid="5908239569510734136">"Suprimeix el convidat"</string>
@@ -644,4 +650,7 @@
<string name="dream_complication_title_cast_info" msgid="4038776652841885084">"Informació d\'emissió"</string>
<string name="avatar_picker_title" msgid="8492884172713170652">"Tria una foto de perfil"</string>
<string name="default_user_icon_description" msgid="6554047177298972638">"Icona d\'usuari predeterminat"</string>
+ <string name="physical_keyboard_title" msgid="4811935435315835220">"Teclat físic"</string>
+ <string name="keyboard_layout_dialog_title" msgid="3927180147005616290">"Tria una disposició de teclat"</string>
+ <string name="keyboard_layout_default_label" msgid="1997292217218546957">"Predeterminat"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-cs/strings.xml b/packages/SettingsLib/res/values-cs/strings.xml
index 014eda9..d7c8ed2 100644
--- a/packages/SettingsLib/res/values-cs/strings.xml
+++ b/packages/SettingsLib/res/values-cs/strings.xml
@@ -533,6 +533,8 @@
<string name="accessibility_manual_zen_less_time" msgid="6828877595848229965">"Kratší doba"</string>
<string name="cancel" msgid="5665114069455378395">"Zrušit"</string>
<string name="okay" msgid="949938843324579502">"OK"</string>
+ <!-- no translation found for done (381184316122520313) -->
+ <skip />
<string name="alarms_and_reminders_label" msgid="6918395649731424294">"Budíky a připomenutí"</string>
<string name="alarms_and_reminders_switch_title" msgid="4939393911531826222">"Povolit nastavování budíků a připomenutí"</string>
<string name="alarms_and_reminders_title" msgid="8819933264635406032">"Budíky a připomenutí"</string>
@@ -551,7 +553,9 @@
<string name="zen_mode_duration_always_prompt_title" msgid="3212996860498119555">"Pokaždé se zeptat"</string>
<string name="zen_mode_forever" msgid="3339224497605461291">"Dokud funkci nevypnete"</string>
<string name="time_unit_just_now" msgid="3006134267292728099">"Právě teď"</string>
- <string name="media_transfer_this_device_name" msgid="2357329267148436433">"Tento telefon"</string>
+ <string name="media_transfer_this_device_name" product="default" msgid="2357329267148436433">"Tento telefon"</string>
+ <!-- no translation found for media_transfer_this_device_name (3714653244000242800) -->
+ <skip />
<string name="media_transfer_this_phone" msgid="7194341457812151531">"Tento telefon"</string>
<string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"Problém s připojením. Vypněte zařízení a znovu jej zapněte"</string>
<string name="media_transfer_wired_device_name" msgid="4447880899964056007">"Kabelové audiozařízení"</string>
@@ -591,7 +595,9 @@
<string name="user_set_lock_button" msgid="1427128184982594856">"Nastavit zámek"</string>
<string name="user_switch_to_user" msgid="6975428297154968543">"Přepnout na uživatele <xliff:g id="USER_NAME">%s</xliff:g>"</string>
<string name="creating_new_user_dialog_message" msgid="7232880257538970375">"Vytváření nového uživatele…"</string>
+ <string name="creating_new_guest_dialog_message" msgid="1114905602181350690">"Vytváření nového hosta…"</string>
<string name="add_user_failed" msgid="4809887794313944872">"Nového uživatele se nepodařilo vytvořit"</string>
+ <string name="add_guest_failed" msgid="8074548434469843443">"Vytvoření nového hosta se nezdařilo"</string>
<string name="user_nickname" msgid="262624187455825083">"Přezdívka"</string>
<string name="guest_new_guest" msgid="3482026122932643557">"Přidat hosta"</string>
<string name="guest_exit_guest" msgid="5908239569510734136">"Odstranit hosta"</string>
@@ -644,4 +650,7 @@
<string name="dream_complication_title_cast_info" msgid="4038776652841885084">"Info o odesílání"</string>
<string name="avatar_picker_title" msgid="8492884172713170652">"Vyberte profilový obrázek"</string>
<string name="default_user_icon_description" msgid="6554047177298972638">"Výchozí uživatelská ikona"</string>
+ <string name="physical_keyboard_title" msgid="4811935435315835220">"Fyzická klávesnice"</string>
+ <string name="keyboard_layout_dialog_title" msgid="3927180147005616290">"Zvolte rozložení klávesnice"</string>
+ <string name="keyboard_layout_default_label" msgid="1997292217218546957">"Výchozí"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-da/strings.xml b/packages/SettingsLib/res/values-da/strings.xml
index d10975d..19caaa5 100644
--- a/packages/SettingsLib/res/values-da/strings.xml
+++ b/packages/SettingsLib/res/values-da/strings.xml
@@ -533,6 +533,8 @@
<string name="accessibility_manual_zen_less_time" msgid="6828877595848229965">"Mindre tid."</string>
<string name="cancel" msgid="5665114069455378395">"Annuller"</string>
<string name="okay" msgid="949938843324579502">"OK"</string>
+ <!-- no translation found for done (381184316122520313) -->
+ <skip />
<string name="alarms_and_reminders_label" msgid="6918395649731424294">"Alarmer og påmindelser"</string>
<string name="alarms_and_reminders_switch_title" msgid="4939393911531826222">"Tillad indstilling af alarmer og påmindelser"</string>
<string name="alarms_and_reminders_title" msgid="8819933264635406032">"Alarmer og påmindelser"</string>
@@ -551,7 +553,9 @@
<string name="zen_mode_duration_always_prompt_title" msgid="3212996860498119555">"Spørg hver gang"</string>
<string name="zen_mode_forever" msgid="3339224497605461291">"Indtil du deaktiverer"</string>
<string name="time_unit_just_now" msgid="3006134267292728099">"Lige nu"</string>
- <string name="media_transfer_this_device_name" msgid="2357329267148436433">"Denne telefon"</string>
+ <string name="media_transfer_this_device_name" product="default" msgid="2357329267148436433">"Denne telefon"</string>
+ <!-- no translation found for media_transfer_this_device_name (3714653244000242800) -->
+ <skip />
<string name="media_transfer_this_phone" msgid="7194341457812151531">"Denne telefon"</string>
<string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"Der kunne ikke oprettes forbindelse. Sluk og tænd enheden"</string>
<string name="media_transfer_wired_device_name" msgid="4447880899964056007">"Lydenhed med ledning"</string>
@@ -591,7 +595,9 @@
<string name="user_set_lock_button" msgid="1427128184982594856">"Konfigurer låseskærmen"</string>
<string name="user_switch_to_user" msgid="6975428297154968543">"Skift til <xliff:g id="USER_NAME">%s</xliff:g>"</string>
<string name="creating_new_user_dialog_message" msgid="7232880257538970375">"Opretter ny bruger…"</string>
+ <string name="creating_new_guest_dialog_message" msgid="1114905602181350690">"Opretter ny gæst…"</string>
<string name="add_user_failed" msgid="4809887794313944872">"Der kunne ikke oprettes en ny bruger"</string>
+ <string name="add_guest_failed" msgid="8074548434469843443">"Der kunne ikke oprettes en ny gæst"</string>
<string name="user_nickname" msgid="262624187455825083">"Kaldenavn"</string>
<string name="guest_new_guest" msgid="3482026122932643557">"Tilføj gæst"</string>
<string name="guest_exit_guest" msgid="5908239569510734136">"Fjern gæsten"</string>
@@ -644,4 +650,7 @@
<string name="dream_complication_title_cast_info" msgid="4038776652841885084">"Cast-oplysninger"</string>
<string name="avatar_picker_title" msgid="8492884172713170652">"Vælg et profilbillede"</string>
<string name="default_user_icon_description" msgid="6554047177298972638">"Ikon for standardbruger"</string>
+ <string name="physical_keyboard_title" msgid="4811935435315835220">"Fysisk tastatur"</string>
+ <string name="keyboard_layout_dialog_title" msgid="3927180147005616290">"Vælg tastaturlayout"</string>
+ <string name="keyboard_layout_default_label" msgid="1997292217218546957">"Standard"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-de/strings.xml b/packages/SettingsLib/res/values-de/strings.xml
index 9b8b3b5..594129b 100644
--- a/packages/SettingsLib/res/values-de/strings.xml
+++ b/packages/SettingsLib/res/values-de/strings.xml
@@ -95,7 +95,7 @@
<string name="bluetooth_disconnecting" msgid="7638892134401574338">"Verbindung wird getrennt..."</string>
<string name="bluetooth_connecting" msgid="5871702668260192755">"Verbindung wird hergestellt..."</string>
<string name="bluetooth_connected" msgid="8065345572198502293">"Mit <xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g> verbunden"</string>
- <string name="bluetooth_pairing" msgid="4269046942588193600">"Verbindung wird hergestellt…"</string>
+ <string name="bluetooth_pairing" msgid="4269046942588193600">"Wird gekoppelt…"</string>
<string name="bluetooth_connected_no_headset" msgid="2224101138659967604">"Mit <xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g> verbunden (kein Telefon-Audio)"</string>
<string name="bluetooth_connected_no_a2dp" msgid="8566874395813947092">"Mit <xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g> verbunden (kein Medien-Audio)"</string>
<string name="bluetooth_connected_no_map" msgid="3381860077002724689">"Mit <xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g> verbunden (kein Nachrichtenzugriff)"</string>
@@ -533,6 +533,8 @@
<string name="accessibility_manual_zen_less_time" msgid="6828877595848229965">"Weniger Zeit."</string>
<string name="cancel" msgid="5665114069455378395">"Abbrechen"</string>
<string name="okay" msgid="949938843324579502">"OK"</string>
+ <!-- no translation found for done (381184316122520313) -->
+ <skip />
<string name="alarms_and_reminders_label" msgid="6918395649731424294">"Wecker und Erinnerungen"</string>
<string name="alarms_and_reminders_switch_title" msgid="4939393911531826222">"Erlauben, Wecker und Erinnerungen einzurichten"</string>
<string name="alarms_and_reminders_title" msgid="8819933264635406032">"Wecker und Erinnerungen"</string>
@@ -551,7 +553,9 @@
<string name="zen_mode_duration_always_prompt_title" msgid="3212996860498119555">"Jedes Mal fragen"</string>
<string name="zen_mode_forever" msgid="3339224497605461291">"Bis zur Deaktivierung"</string>
<string name="time_unit_just_now" msgid="3006134267292728099">"Gerade eben"</string>
- <string name="media_transfer_this_device_name" msgid="2357329267148436433">"Dieses Smartphone"</string>
+ <string name="media_transfer_this_device_name" product="default" msgid="2357329267148436433">"Dieses Smartphone"</string>
+ <!-- no translation found for media_transfer_this_device_name (3714653244000242800) -->
+ <skip />
<string name="media_transfer_this_phone" msgid="7194341457812151531">"Dieses Smartphone"</string>
<string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"Verbindung kann nicht hergestellt werden. Schalte das Gerät aus & und wieder ein."</string>
<string name="media_transfer_wired_device_name" msgid="4447880899964056007">"Netzbetriebenes Audiogerät"</string>
@@ -591,7 +595,9 @@
<string name="user_set_lock_button" msgid="1427128184982594856">"Sperre einrichten"</string>
<string name="user_switch_to_user" msgid="6975428297154968543">"Zu <xliff:g id="USER_NAME">%s</xliff:g> wechseln"</string>
<string name="creating_new_user_dialog_message" msgid="7232880257538970375">"Neuer Nutzer wird erstellt…"</string>
+ <string name="creating_new_guest_dialog_message" msgid="1114905602181350690">"Neuer Gast wird erstellt…"</string>
<string name="add_user_failed" msgid="4809887794313944872">"Nutzer konnte nicht erstellt werden"</string>
+ <string name="add_guest_failed" msgid="8074548434469843443">"Fehler beim Erstellen eines neuen Gasts"</string>
<string name="user_nickname" msgid="262624187455825083">"Alias"</string>
<string name="guest_new_guest" msgid="3482026122932643557">"Gast hinzufügen"</string>
<string name="guest_exit_guest" msgid="5908239569510734136">"Gast entfernen"</string>
@@ -644,4 +650,7 @@
<string name="dream_complication_title_cast_info" msgid="4038776652841885084">"Streaming-Info"</string>
<string name="avatar_picker_title" msgid="8492884172713170652">"Profilbild auswählen"</string>
<string name="default_user_icon_description" msgid="6554047177298972638">"Standardmäßiges Nutzersymbol"</string>
+ <string name="physical_keyboard_title" msgid="4811935435315835220">"Physische Tastatur"</string>
+ <string name="keyboard_layout_dialog_title" msgid="3927180147005616290">"Tastaturlayout wählen"</string>
+ <string name="keyboard_layout_default_label" msgid="1997292217218546957">"Standard"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-el/strings.xml b/packages/SettingsLib/res/values-el/strings.xml
index cb6ec17..b913da7 100644
--- a/packages/SettingsLib/res/values-el/strings.xml
+++ b/packages/SettingsLib/res/values-el/strings.xml
@@ -533,6 +533,8 @@
<string name="accessibility_manual_zen_less_time" msgid="6828877595848229965">"Λιγότερη ώρα."</string>
<string name="cancel" msgid="5665114069455378395">"Ακύρωση"</string>
<string name="okay" msgid="949938843324579502">"ΟΚ"</string>
+ <!-- no translation found for done (381184316122520313) -->
+ <skip />
<string name="alarms_and_reminders_label" msgid="6918395649731424294">"Ξυπνητήρια και ειδοποιήσεις"</string>
<string name="alarms_and_reminders_switch_title" msgid="4939393911531826222">"Να επιτρέπεται ο ορισμός ξυπνητ. και υπενθυμίσεων"</string>
<string name="alarms_and_reminders_title" msgid="8819933264635406032">"Ξυπνητήρια και υπενθυμίσεις"</string>
@@ -551,7 +553,9 @@
<string name="zen_mode_duration_always_prompt_title" msgid="3212996860498119555">"Να ερωτώμαι κάθε φορά"</string>
<string name="zen_mode_forever" msgid="3339224497605461291">"Μέχρι την απενεργοποίηση"</string>
<string name="time_unit_just_now" msgid="3006134267292728099">"Μόλις τώρα"</string>
- <string name="media_transfer_this_device_name" msgid="2357329267148436433">"Αυτό το τηλέφωνο"</string>
+ <string name="media_transfer_this_device_name" product="default" msgid="2357329267148436433">"Αυτό το τηλέφωνο"</string>
+ <!-- no translation found for media_transfer_this_device_name (3714653244000242800) -->
+ <skip />
<string name="media_transfer_this_phone" msgid="7194341457812151531">"Αυτό το τηλέφωνο"</string>
<string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"Πρόβλημα κατά τη σύνδεση. Απενεργοποιήστε τη συσκευή και ενεργοποιήστε την ξανά"</string>
<string name="media_transfer_wired_device_name" msgid="4447880899964056007">"Ενσύρματη συσκευή ήχου"</string>
@@ -591,7 +595,9 @@
<string name="user_set_lock_button" msgid="1427128184982594856">"Ορισμός κλειδώματος"</string>
<string name="user_switch_to_user" msgid="6975428297154968543">"Εναλλαγή σε <xliff:g id="USER_NAME">%s</xliff:g>"</string>
<string name="creating_new_user_dialog_message" msgid="7232880257538970375">"Δημιουργία νέου χρήστη…"</string>
+ <string name="creating_new_guest_dialog_message" msgid="1114905602181350690">"Δημιουργία νέου προσκεκλημένου…"</string>
<string name="add_user_failed" msgid="4809887794313944872">"Η δημιουργία νέου χρήστη απέτυχε"</string>
+ <string name="add_guest_failed" msgid="8074548434469843443">"Αποτυχία δημιουργίας νέου προσκεκλημένου"</string>
<string name="user_nickname" msgid="262624187455825083">"Ψευδώνυμο"</string>
<string name="guest_new_guest" msgid="3482026122932643557">"Προσθήκη επισκέπτη"</string>
<string name="guest_exit_guest" msgid="5908239569510734136">"Κατάργηση επισκέπτη"</string>
@@ -644,4 +650,7 @@
<string name="dream_complication_title_cast_info" msgid="4038776652841885084">"Πληροφορίες ηθοποιών"</string>
<string name="avatar_picker_title" msgid="8492884172713170652">"Επιλογή φωτογραφίας προφίλ"</string>
<string name="default_user_icon_description" msgid="6554047177298972638">"Προεπιλεγμένο εικονίδιο χρήστη"</string>
+ <string name="physical_keyboard_title" msgid="4811935435315835220">"Φυσικό πληκτρολόγιο"</string>
+ <string name="keyboard_layout_dialog_title" msgid="3927180147005616290">"Επιλέξτε διάταξη πληκτρολογίου"</string>
+ <string name="keyboard_layout_default_label" msgid="1997292217218546957">"Προεπιλογή"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-en-rAU/strings.xml b/packages/SettingsLib/res/values-en-rAU/strings.xml
index c2c14b4..d6dce99 100644
--- a/packages/SettingsLib/res/values-en-rAU/strings.xml
+++ b/packages/SettingsLib/res/values-en-rAU/strings.xml
@@ -533,6 +533,7 @@
<string name="accessibility_manual_zen_less_time" msgid="6828877595848229965">"Less time."</string>
<string name="cancel" msgid="5665114069455378395">"Cancel"</string>
<string name="okay" msgid="949938843324579502">"OK"</string>
+ <string name="done" msgid="381184316122520313">"Done"</string>
<string name="alarms_and_reminders_label" msgid="6918395649731424294">"Alarms and reminders"</string>
<string name="alarms_and_reminders_switch_title" msgid="4939393911531826222">"Allow setting alarms and reminders"</string>
<string name="alarms_and_reminders_title" msgid="8819933264635406032">"Alarms & reminders"</string>
@@ -551,7 +552,9 @@
<string name="zen_mode_duration_always_prompt_title" msgid="3212996860498119555">"Ask every time"</string>
<string name="zen_mode_forever" msgid="3339224497605461291">"Until you turn off"</string>
<string name="time_unit_just_now" msgid="3006134267292728099">"Just now"</string>
- <string name="media_transfer_this_device_name" msgid="2357329267148436433">"This phone"</string>
+ <string name="media_transfer_this_device_name" product="default" msgid="2357329267148436433">"This phone"</string>
+ <!-- no translation found for media_transfer_this_device_name (3714653244000242800) -->
+ <skip />
<string name="media_transfer_this_phone" msgid="7194341457812151531">"This phone"</string>
<string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"Problem connecting. Turn device off and back on"</string>
<string name="media_transfer_wired_device_name" msgid="4447880899964056007">"Wired audio device"</string>
@@ -591,7 +594,9 @@
<string name="user_set_lock_button" msgid="1427128184982594856">"Set lock"</string>
<string name="user_switch_to_user" msgid="6975428297154968543">"Switch to <xliff:g id="USER_NAME">%s</xliff:g>"</string>
<string name="creating_new_user_dialog_message" msgid="7232880257538970375">"Creating new user…"</string>
+ <string name="creating_new_guest_dialog_message" msgid="1114905602181350690">"Creating new guest…"</string>
<string name="add_user_failed" msgid="4809887794313944872">"Failed to create a new user"</string>
+ <string name="add_guest_failed" msgid="8074548434469843443">"Failed to create a new guest"</string>
<string name="user_nickname" msgid="262624187455825083">"Nickname"</string>
<string name="guest_new_guest" msgid="3482026122932643557">"Add guest"</string>
<string name="guest_exit_guest" msgid="5908239569510734136">"Remove guest"</string>
@@ -644,4 +649,10 @@
<string name="dream_complication_title_cast_info" msgid="4038776652841885084">"Cast info"</string>
<string name="avatar_picker_title" msgid="8492884172713170652">"Choose a profile picture"</string>
<string name="default_user_icon_description" msgid="6554047177298972638">"Default user icon"</string>
+ <!-- no translation found for physical_keyboard_title (4811935435315835220) -->
+ <skip />
+ <!-- no translation found for keyboard_layout_dialog_title (3927180147005616290) -->
+ <skip />
+ <!-- no translation found for keyboard_layout_default_label (1997292217218546957) -->
+ <skip />
</resources>
diff --git a/packages/SettingsLib/res/values-en-rCA/strings.xml b/packages/SettingsLib/res/values-en-rCA/strings.xml
index 91d4a31..76d1a94 100644
--- a/packages/SettingsLib/res/values-en-rCA/strings.xml
+++ b/packages/SettingsLib/res/values-en-rCA/strings.xml
@@ -533,6 +533,7 @@
<string name="accessibility_manual_zen_less_time" msgid="6828877595848229965">"Less time."</string>
<string name="cancel" msgid="5665114069455378395">"Cancel"</string>
<string name="okay" msgid="949938843324579502">"OK"</string>
+ <string name="done" msgid="381184316122520313">"Done"</string>
<string name="alarms_and_reminders_label" msgid="6918395649731424294">"Alarms and reminders"</string>
<string name="alarms_and_reminders_switch_title" msgid="4939393911531826222">"Allow setting alarms and reminders"</string>
<string name="alarms_and_reminders_title" msgid="8819933264635406032">"Alarms & reminders"</string>
@@ -551,7 +552,9 @@
<string name="zen_mode_duration_always_prompt_title" msgid="3212996860498119555">"Ask every time"</string>
<string name="zen_mode_forever" msgid="3339224497605461291">"Until you turn off"</string>
<string name="time_unit_just_now" msgid="3006134267292728099">"Just now"</string>
- <string name="media_transfer_this_device_name" msgid="2357329267148436433">"This phone"</string>
+ <string name="media_transfer_this_device_name" product="default" msgid="2357329267148436433">"This phone"</string>
+ <!-- no translation found for media_transfer_this_device_name (3714653244000242800) -->
+ <skip />
<string name="media_transfer_this_phone" msgid="7194341457812151531">"This phone"</string>
<string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"Problem connecting. Turn device off and back on"</string>
<string name="media_transfer_wired_device_name" msgid="4447880899964056007">"Wired audio device"</string>
@@ -591,7 +594,9 @@
<string name="user_set_lock_button" msgid="1427128184982594856">"Set lock"</string>
<string name="user_switch_to_user" msgid="6975428297154968543">"Switch to <xliff:g id="USER_NAME">%s</xliff:g>"</string>
<string name="creating_new_user_dialog_message" msgid="7232880257538970375">"Creating new user…"</string>
+ <string name="creating_new_guest_dialog_message" msgid="1114905602181350690">"Creating new guest…"</string>
<string name="add_user_failed" msgid="4809887794313944872">"Failed to create a new user"</string>
+ <string name="add_guest_failed" msgid="8074548434469843443">"Failed to create a new guest"</string>
<string name="user_nickname" msgid="262624187455825083">"Nickname"</string>
<string name="guest_new_guest" msgid="3482026122932643557">"Add guest"</string>
<string name="guest_exit_guest" msgid="5908239569510734136">"Remove guest"</string>
@@ -644,4 +649,10 @@
<string name="dream_complication_title_cast_info" msgid="4038776652841885084">"Cast info"</string>
<string name="avatar_picker_title" msgid="8492884172713170652">"Choose a profile picture"</string>
<string name="default_user_icon_description" msgid="6554047177298972638">"Default user icon"</string>
+ <!-- no translation found for physical_keyboard_title (4811935435315835220) -->
+ <skip />
+ <!-- no translation found for keyboard_layout_dialog_title (3927180147005616290) -->
+ <skip />
+ <!-- no translation found for keyboard_layout_default_label (1997292217218546957) -->
+ <skip />
</resources>
diff --git a/packages/SettingsLib/res/values-en-rGB/strings.xml b/packages/SettingsLib/res/values-en-rGB/strings.xml
index c2c14b4..d6dce99 100644
--- a/packages/SettingsLib/res/values-en-rGB/strings.xml
+++ b/packages/SettingsLib/res/values-en-rGB/strings.xml
@@ -533,6 +533,7 @@
<string name="accessibility_manual_zen_less_time" msgid="6828877595848229965">"Less time."</string>
<string name="cancel" msgid="5665114069455378395">"Cancel"</string>
<string name="okay" msgid="949938843324579502">"OK"</string>
+ <string name="done" msgid="381184316122520313">"Done"</string>
<string name="alarms_and_reminders_label" msgid="6918395649731424294">"Alarms and reminders"</string>
<string name="alarms_and_reminders_switch_title" msgid="4939393911531826222">"Allow setting alarms and reminders"</string>
<string name="alarms_and_reminders_title" msgid="8819933264635406032">"Alarms & reminders"</string>
@@ -551,7 +552,9 @@
<string name="zen_mode_duration_always_prompt_title" msgid="3212996860498119555">"Ask every time"</string>
<string name="zen_mode_forever" msgid="3339224497605461291">"Until you turn off"</string>
<string name="time_unit_just_now" msgid="3006134267292728099">"Just now"</string>
- <string name="media_transfer_this_device_name" msgid="2357329267148436433">"This phone"</string>
+ <string name="media_transfer_this_device_name" product="default" msgid="2357329267148436433">"This phone"</string>
+ <!-- no translation found for media_transfer_this_device_name (3714653244000242800) -->
+ <skip />
<string name="media_transfer_this_phone" msgid="7194341457812151531">"This phone"</string>
<string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"Problem connecting. Turn device off and back on"</string>
<string name="media_transfer_wired_device_name" msgid="4447880899964056007">"Wired audio device"</string>
@@ -591,7 +594,9 @@
<string name="user_set_lock_button" msgid="1427128184982594856">"Set lock"</string>
<string name="user_switch_to_user" msgid="6975428297154968543">"Switch to <xliff:g id="USER_NAME">%s</xliff:g>"</string>
<string name="creating_new_user_dialog_message" msgid="7232880257538970375">"Creating new user…"</string>
+ <string name="creating_new_guest_dialog_message" msgid="1114905602181350690">"Creating new guest…"</string>
<string name="add_user_failed" msgid="4809887794313944872">"Failed to create a new user"</string>
+ <string name="add_guest_failed" msgid="8074548434469843443">"Failed to create a new guest"</string>
<string name="user_nickname" msgid="262624187455825083">"Nickname"</string>
<string name="guest_new_guest" msgid="3482026122932643557">"Add guest"</string>
<string name="guest_exit_guest" msgid="5908239569510734136">"Remove guest"</string>
@@ -644,4 +649,10 @@
<string name="dream_complication_title_cast_info" msgid="4038776652841885084">"Cast info"</string>
<string name="avatar_picker_title" msgid="8492884172713170652">"Choose a profile picture"</string>
<string name="default_user_icon_description" msgid="6554047177298972638">"Default user icon"</string>
+ <!-- no translation found for physical_keyboard_title (4811935435315835220) -->
+ <skip />
+ <!-- no translation found for keyboard_layout_dialog_title (3927180147005616290) -->
+ <skip />
+ <!-- no translation found for keyboard_layout_default_label (1997292217218546957) -->
+ <skip />
</resources>
diff --git a/packages/SettingsLib/res/values-en-rIN/strings.xml b/packages/SettingsLib/res/values-en-rIN/strings.xml
index c2c14b4..d6dce99 100644
--- a/packages/SettingsLib/res/values-en-rIN/strings.xml
+++ b/packages/SettingsLib/res/values-en-rIN/strings.xml
@@ -533,6 +533,7 @@
<string name="accessibility_manual_zen_less_time" msgid="6828877595848229965">"Less time."</string>
<string name="cancel" msgid="5665114069455378395">"Cancel"</string>
<string name="okay" msgid="949938843324579502">"OK"</string>
+ <string name="done" msgid="381184316122520313">"Done"</string>
<string name="alarms_and_reminders_label" msgid="6918395649731424294">"Alarms and reminders"</string>
<string name="alarms_and_reminders_switch_title" msgid="4939393911531826222">"Allow setting alarms and reminders"</string>
<string name="alarms_and_reminders_title" msgid="8819933264635406032">"Alarms & reminders"</string>
@@ -551,7 +552,9 @@
<string name="zen_mode_duration_always_prompt_title" msgid="3212996860498119555">"Ask every time"</string>
<string name="zen_mode_forever" msgid="3339224497605461291">"Until you turn off"</string>
<string name="time_unit_just_now" msgid="3006134267292728099">"Just now"</string>
- <string name="media_transfer_this_device_name" msgid="2357329267148436433">"This phone"</string>
+ <string name="media_transfer_this_device_name" product="default" msgid="2357329267148436433">"This phone"</string>
+ <!-- no translation found for media_transfer_this_device_name (3714653244000242800) -->
+ <skip />
<string name="media_transfer_this_phone" msgid="7194341457812151531">"This phone"</string>
<string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"Problem connecting. Turn device off and back on"</string>
<string name="media_transfer_wired_device_name" msgid="4447880899964056007">"Wired audio device"</string>
@@ -591,7 +594,9 @@
<string name="user_set_lock_button" msgid="1427128184982594856">"Set lock"</string>
<string name="user_switch_to_user" msgid="6975428297154968543">"Switch to <xliff:g id="USER_NAME">%s</xliff:g>"</string>
<string name="creating_new_user_dialog_message" msgid="7232880257538970375">"Creating new user…"</string>
+ <string name="creating_new_guest_dialog_message" msgid="1114905602181350690">"Creating new guest…"</string>
<string name="add_user_failed" msgid="4809887794313944872">"Failed to create a new user"</string>
+ <string name="add_guest_failed" msgid="8074548434469843443">"Failed to create a new guest"</string>
<string name="user_nickname" msgid="262624187455825083">"Nickname"</string>
<string name="guest_new_guest" msgid="3482026122932643557">"Add guest"</string>
<string name="guest_exit_guest" msgid="5908239569510734136">"Remove guest"</string>
@@ -644,4 +649,10 @@
<string name="dream_complication_title_cast_info" msgid="4038776652841885084">"Cast info"</string>
<string name="avatar_picker_title" msgid="8492884172713170652">"Choose a profile picture"</string>
<string name="default_user_icon_description" msgid="6554047177298972638">"Default user icon"</string>
+ <!-- no translation found for physical_keyboard_title (4811935435315835220) -->
+ <skip />
+ <!-- no translation found for keyboard_layout_dialog_title (3927180147005616290) -->
+ <skip />
+ <!-- no translation found for keyboard_layout_default_label (1997292217218546957) -->
+ <skip />
</resources>
diff --git a/packages/SettingsLib/res/values-en-rXC/strings.xml b/packages/SettingsLib/res/values-en-rXC/strings.xml
index ebb1d0e..f02d0c5 100644
--- a/packages/SettingsLib/res/values-en-rXC/strings.xml
+++ b/packages/SettingsLib/res/values-en-rXC/strings.xml
@@ -533,6 +533,7 @@
<string name="accessibility_manual_zen_less_time" msgid="6828877595848229965">"Less time."</string>
<string name="cancel" msgid="5665114069455378395">"Cancel"</string>
<string name="okay" msgid="949938843324579502">"OK"</string>
+ <string name="done" msgid="381184316122520313">"Done"</string>
<string name="alarms_and_reminders_label" msgid="6918395649731424294">"Alarms and reminders"</string>
<string name="alarms_and_reminders_switch_title" msgid="4939393911531826222">"Allow setting alarms and reminders"</string>
<string name="alarms_and_reminders_title" msgid="8819933264635406032">"Alarms & reminders"</string>
@@ -551,7 +552,9 @@
<string name="zen_mode_duration_always_prompt_title" msgid="3212996860498119555">"Ask every time"</string>
<string name="zen_mode_forever" msgid="3339224497605461291">"Until you turn off"</string>
<string name="time_unit_just_now" msgid="3006134267292728099">"Just now"</string>
- <string name="media_transfer_this_device_name" msgid="2357329267148436433">"This phone"</string>
+ <string name="media_transfer_this_device_name" product="default" msgid="2357329267148436433">"This phone"</string>
+ <!-- no translation found for media_transfer_this_device_name (3714653244000242800) -->
+ <skip />
<string name="media_transfer_this_phone" msgid="7194341457812151531">"This phone"</string>
<string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"Problem connecting. Turn device off & back on"</string>
<string name="media_transfer_wired_device_name" msgid="4447880899964056007">"Wired audio device"</string>
@@ -591,7 +594,9 @@
<string name="user_set_lock_button" msgid="1427128184982594856">"Set lock"</string>
<string name="user_switch_to_user" msgid="6975428297154968543">"Switch to <xliff:g id="USER_NAME">%s</xliff:g>"</string>
<string name="creating_new_user_dialog_message" msgid="7232880257538970375">"Creating new user…"</string>
+ <string name="creating_new_guest_dialog_message" msgid="1114905602181350690">"Creating new guest…"</string>
<string name="add_user_failed" msgid="4809887794313944872">"Failed to create a new user"</string>
+ <string name="add_guest_failed" msgid="8074548434469843443">"Failed to create a new guest"</string>
<string name="user_nickname" msgid="262624187455825083">"Nickname"</string>
<string name="guest_new_guest" msgid="3482026122932643557">"Add guest"</string>
<string name="guest_exit_guest" msgid="5908239569510734136">"Remove guest"</string>
@@ -644,4 +649,7 @@
<string name="dream_complication_title_cast_info" msgid="4038776652841885084">"Cast Info"</string>
<string name="avatar_picker_title" msgid="8492884172713170652">"Choose a profile picture"</string>
<string name="default_user_icon_description" msgid="6554047177298972638">"Default user icon"</string>
+ <string name="physical_keyboard_title" msgid="4811935435315835220">"Physical keyboard"</string>
+ <string name="keyboard_layout_dialog_title" msgid="3927180147005616290">"Choose keyboard layout"</string>
+ <string name="keyboard_layout_default_label" msgid="1997292217218546957">"Default"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-es-rUS/strings.xml b/packages/SettingsLib/res/values-es-rUS/strings.xml
index 254d41e..49b4b51 100644
--- a/packages/SettingsLib/res/values-es-rUS/strings.xml
+++ b/packages/SettingsLib/res/values-es-rUS/strings.xml
@@ -533,6 +533,8 @@
<string name="accessibility_manual_zen_less_time" msgid="6828877595848229965">"Menos tiempo"</string>
<string name="cancel" msgid="5665114069455378395">"Cancelar"</string>
<string name="okay" msgid="949938843324579502">"Aceptar"</string>
+ <!-- no translation found for done (381184316122520313) -->
+ <skip />
<string name="alarms_and_reminders_label" msgid="6918395649731424294">"Alarmas y recordatorios"</string>
<string name="alarms_and_reminders_switch_title" msgid="4939393911531826222">"Permitir configuración de alarmas y recordatorios"</string>
<string name="alarms_and_reminders_title" msgid="8819933264635406032">"Alarmas y recordatorios"</string>
@@ -551,7 +553,9 @@
<string name="zen_mode_duration_always_prompt_title" msgid="3212996860498119555">"Preguntar siempre"</string>
<string name="zen_mode_forever" msgid="3339224497605461291">"Hasta que lo desactives"</string>
<string name="time_unit_just_now" msgid="3006134267292728099">"Recién"</string>
- <string name="media_transfer_this_device_name" msgid="2357329267148436433">"Este teléfono"</string>
+ <string name="media_transfer_this_device_name" product="default" msgid="2357329267148436433">"Este teléfono"</string>
+ <!-- no translation found for media_transfer_this_device_name (3714653244000242800) -->
+ <skip />
<string name="media_transfer_this_phone" msgid="7194341457812151531">"Este teléfono"</string>
<string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"Error al establecer la conexión. Apaga el dispositivo y vuelve a encenderlo."</string>
<string name="media_transfer_wired_device_name" msgid="4447880899964056007">"Dispositivo de audio con cable"</string>
@@ -591,7 +595,9 @@
<string name="user_set_lock_button" msgid="1427128184982594856">"Configurar bloqueo"</string>
<string name="user_switch_to_user" msgid="6975428297154968543">"Cambiar a <xliff:g id="USER_NAME">%s</xliff:g>"</string>
<string name="creating_new_user_dialog_message" msgid="7232880257538970375">"Creando usuario nuevo…"</string>
+ <string name="creating_new_guest_dialog_message" msgid="1114905602181350690">"Creando nuevo invitado…"</string>
<string name="add_user_failed" msgid="4809887794313944872">"No se pudo crear el usuario nuevo"</string>
+ <string name="add_guest_failed" msgid="8074548434469843443">"No se pudo crear un nuevo invitado"</string>
<string name="user_nickname" msgid="262624187455825083">"Sobrenombre"</string>
<string name="guest_new_guest" msgid="3482026122932643557">"Agregar invitado"</string>
<string name="guest_exit_guest" msgid="5908239569510734136">"Quitar invitado"</string>
@@ -644,4 +650,10 @@
<string name="dream_complication_title_cast_info" msgid="4038776652841885084">"Info de reparto"</string>
<string name="avatar_picker_title" msgid="8492884172713170652">"Elige una foto de perfil"</string>
<string name="default_user_icon_description" msgid="6554047177298972638">"Ícono de usuario predeterminado"</string>
+ <!-- no translation found for physical_keyboard_title (4811935435315835220) -->
+ <skip />
+ <!-- no translation found for keyboard_layout_dialog_title (3927180147005616290) -->
+ <skip />
+ <!-- no translation found for keyboard_layout_default_label (1997292217218546957) -->
+ <skip />
</resources>
diff --git a/packages/SettingsLib/res/values-es/strings.xml b/packages/SettingsLib/res/values-es/strings.xml
index 447475f..d34beed 100644
--- a/packages/SettingsLib/res/values-es/strings.xml
+++ b/packages/SettingsLib/res/values-es/strings.xml
@@ -533,6 +533,8 @@
<string name="accessibility_manual_zen_less_time" msgid="6828877595848229965">"Menos tiempo."</string>
<string name="cancel" msgid="5665114069455378395">"Cancelar"</string>
<string name="okay" msgid="949938843324579502">"Aceptar"</string>
+ <!-- no translation found for done (381184316122520313) -->
+ <skip />
<string name="alarms_and_reminders_label" msgid="6918395649731424294">"Alarmas y recordatorios"</string>
<string name="alarms_and_reminders_switch_title" msgid="4939393911531826222">"Permitir la programación de alarmas y recordatorios"</string>
<string name="alarms_and_reminders_title" msgid="8819933264635406032">"Alarmas y recordatorios"</string>
@@ -551,7 +553,9 @@
<string name="zen_mode_duration_always_prompt_title" msgid="3212996860498119555">"Preguntar siempre"</string>
<string name="zen_mode_forever" msgid="3339224497605461291">"Hasta que lo desactives"</string>
<string name="time_unit_just_now" msgid="3006134267292728099">"justo ahora"</string>
- <string name="media_transfer_this_device_name" msgid="2357329267148436433">"Este teléfono"</string>
+ <string name="media_transfer_this_device_name" product="default" msgid="2357329267148436433">"Este teléfono"</string>
+ <!-- no translation found for media_transfer_this_device_name (3714653244000242800) -->
+ <skip />
<string name="media_transfer_this_phone" msgid="7194341457812151531">"Este teléfono"</string>
<string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"No se ha podido conectar; reinicia el dispositivo"</string>
<string name="media_transfer_wired_device_name" msgid="4447880899964056007">"Dispositivo de audio con cable"</string>
@@ -591,7 +595,9 @@
<string name="user_set_lock_button" msgid="1427128184982594856">"Establecer bloqueo"</string>
<string name="user_switch_to_user" msgid="6975428297154968543">"Cambiar a <xliff:g id="USER_NAME">%s</xliff:g>"</string>
<string name="creating_new_user_dialog_message" msgid="7232880257538970375">"Creando usuario…"</string>
+ <string name="creating_new_guest_dialog_message" msgid="1114905602181350690">"Creando nuevo invitado…"</string>
<string name="add_user_failed" msgid="4809887794313944872">"No se ha podido crear el usuario"</string>
+ <string name="add_guest_failed" msgid="8074548434469843443">"No se ha podido crear un nuevo invitado"</string>
<string name="user_nickname" msgid="262624187455825083">"Apodo"</string>
<string name="guest_new_guest" msgid="3482026122932643557">"Añadir invitado"</string>
<string name="guest_exit_guest" msgid="5908239569510734136">"Quitar invitado"</string>
@@ -639,9 +645,12 @@
<string name="accessibility_no_calling" msgid="3540827068323895748">"Sin llamadas."</string>
<string name="dream_complication_title_time" msgid="701747800712893499">"Hora"</string>
<string name="dream_complication_title_date" msgid="8661176085446135789">"Fecha"</string>
- <string name="dream_complication_title_weather" msgid="598609151677172783">"Info. meteorológica"</string>
+ <string name="dream_complication_title_weather" msgid="598609151677172783">"Tiempo"</string>
<string name="dream_complication_title_aqi" msgid="4587552608957834110">"Calidad del aire"</string>
<string name="dream_complication_title_cast_info" msgid="4038776652841885084">"Info. de emisión"</string>
<string name="avatar_picker_title" msgid="8492884172713170652">"Elige una imagen de perfil"</string>
<string name="default_user_icon_description" msgid="6554047177298972638">"Icono de usuario predeterminado"</string>
+ <string name="physical_keyboard_title" msgid="4811935435315835220">"Teclado físico"</string>
+ <string name="keyboard_layout_dialog_title" msgid="3927180147005616290">"Elige el diseño del teclado"</string>
+ <string name="keyboard_layout_default_label" msgid="1997292217218546957">"Predeterminado"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-et/strings.xml b/packages/SettingsLib/res/values-et/strings.xml
index 2c8a943..a5fa201 100644
--- a/packages/SettingsLib/res/values-et/strings.xml
+++ b/packages/SettingsLib/res/values-et/strings.xml
@@ -533,6 +533,8 @@
<string name="accessibility_manual_zen_less_time" msgid="6828877595848229965">"Lühem aeg."</string>
<string name="cancel" msgid="5665114069455378395">"Tühista"</string>
<string name="okay" msgid="949938843324579502">"OK"</string>
+ <!-- no translation found for done (381184316122520313) -->
+ <skip />
<string name="alarms_and_reminders_label" msgid="6918395649731424294">"Alarmid ja meeldetuletused"</string>
<string name="alarms_and_reminders_switch_title" msgid="4939393911531826222">"Luba alarmide ja meeldetuletuste määramine"</string>
<string name="alarms_and_reminders_title" msgid="8819933264635406032">"Alarmid ja meeldetuletused"</string>
@@ -551,7 +553,9 @@
<string name="zen_mode_duration_always_prompt_title" msgid="3212996860498119555">"Küsi iga kord"</string>
<string name="zen_mode_forever" msgid="3339224497605461291">"Kuni välja lülitate"</string>
<string name="time_unit_just_now" msgid="3006134267292728099">"Äsja"</string>
- <string name="media_transfer_this_device_name" msgid="2357329267148436433">"See telefon"</string>
+ <string name="media_transfer_this_device_name" product="default" msgid="2357329267148436433">"See telefon"</string>
+ <!-- no translation found for media_transfer_this_device_name (3714653244000242800) -->
+ <skip />
<string name="media_transfer_this_phone" msgid="7194341457812151531">"See telefon"</string>
<string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"Probleem ühendamisel. Lülitage seade välja ja uuesti sisse"</string>
<string name="media_transfer_wired_device_name" msgid="4447880899964056007">"Juhtmega heliseade"</string>
@@ -591,7 +595,9 @@
<string name="user_set_lock_button" msgid="1427128184982594856">"Määra lukk"</string>
<string name="user_switch_to_user" msgid="6975428297154968543">"Lülita kasutajale <xliff:g id="USER_NAME">%s</xliff:g>"</string>
<string name="creating_new_user_dialog_message" msgid="7232880257538970375">"Uue kasutaja loomine …"</string>
+ <string name="creating_new_guest_dialog_message" msgid="1114905602181350690">"Uue külalise loomine …"</string>
<string name="add_user_failed" msgid="4809887794313944872">"Uue kasutaja loomine ebaõnnestus"</string>
+ <string name="add_guest_failed" msgid="8074548434469843443">"Uue külalise loomine ei õnnestunud"</string>
<string name="user_nickname" msgid="262624187455825083">"Hüüdnimi"</string>
<string name="guest_new_guest" msgid="3482026122932643557">"Lisa külaline"</string>
<string name="guest_exit_guest" msgid="5908239569510734136">"Eemalda külaline"</string>
@@ -644,4 +650,7 @@
<string name="dream_complication_title_cast_info" msgid="4038776652841885084">"Osatäitjate teave"</string>
<string name="avatar_picker_title" msgid="8492884172713170652">"Valige profiilipilt"</string>
<string name="default_user_icon_description" msgid="6554047177298972638">"Vaikekasutajaikoon"</string>
+ <string name="physical_keyboard_title" msgid="4811935435315835220">"Füüsiline klaviatuur"</string>
+ <string name="keyboard_layout_dialog_title" msgid="3927180147005616290">"Klaviatuuri paigutuse valimine"</string>
+ <string name="keyboard_layout_default_label" msgid="1997292217218546957">"Vaikimisi"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-eu/strings.xml b/packages/SettingsLib/res/values-eu/strings.xml
index 019119e..13ffee7 100644
--- a/packages/SettingsLib/res/values-eu/strings.xml
+++ b/packages/SettingsLib/res/values-eu/strings.xml
@@ -533,6 +533,8 @@
<string name="accessibility_manual_zen_less_time" msgid="6828877595848229965">"Denbora gutxiago."</string>
<string name="cancel" msgid="5665114069455378395">"Utzi"</string>
<string name="okay" msgid="949938843324579502">"Ados"</string>
+ <!-- no translation found for done (381184316122520313) -->
+ <skip />
<string name="alarms_and_reminders_label" msgid="6918395649731424294">"Alarmak eta abisuak"</string>
<string name="alarms_and_reminders_switch_title" msgid="4939393911531826222">"Eman alarmak eta abisuak ezartzeko baimena"</string>
<string name="alarms_and_reminders_title" msgid="8819933264635406032">"Alarmak eta abisuak"</string>
@@ -551,7 +553,9 @@
<string name="zen_mode_duration_always_prompt_title" msgid="3212996860498119555">"Galdetu beti"</string>
<string name="zen_mode_forever" msgid="3339224497605461291">"Zuk desaktibatu arte"</string>
<string name="time_unit_just_now" msgid="3006134267292728099">"Oraintxe"</string>
- <string name="media_transfer_this_device_name" msgid="2357329267148436433">"Telefono hau"</string>
+ <string name="media_transfer_this_device_name" product="default" msgid="2357329267148436433">"Telefono hau"</string>
+ <!-- no translation found for media_transfer_this_device_name (3714653244000242800) -->
+ <skip />
<string name="media_transfer_this_phone" msgid="7194341457812151531">"Telefono hau"</string>
<string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"Arazo bat izan da konektatzean. Itzali gailua eta pitz ezazu berriro."</string>
<string name="media_transfer_wired_device_name" msgid="4447880899964056007">"Audio-gailu kableduna"</string>
@@ -591,7 +595,9 @@
<string name="user_set_lock_button" msgid="1427128184982594856">"Ezarri blokeoa"</string>
<string name="user_switch_to_user" msgid="6975428297154968543">"Aldatu <xliff:g id="USER_NAME">%s</xliff:g> erabiltzailera"</string>
<string name="creating_new_user_dialog_message" msgid="7232880257538970375">"Beste erabiltzaile bat sortzen…"</string>
+ <string name="creating_new_guest_dialog_message" msgid="1114905602181350690">"Beste gonbidatu bat sortzen…"</string>
<string name="add_user_failed" msgid="4809887794313944872">"Ezin izan da sortu erabiltzailea"</string>
+ <string name="add_guest_failed" msgid="8074548434469843443">"Ezin izan da sortu beste gonbidatu bat"</string>
<string name="user_nickname" msgid="262624187455825083">"Goitizena"</string>
<string name="guest_new_guest" msgid="3482026122932643557">"Gehitu gonbidatua"</string>
<string name="guest_exit_guest" msgid="5908239569510734136">"Kendu gonbidatua"</string>
@@ -644,4 +650,10 @@
<string name="dream_complication_title_cast_info" msgid="4038776652841885084">"Igorpenari buruzko informazioa"</string>
<string name="avatar_picker_title" msgid="8492884172713170652">"Aukeratu profileko argazki bat"</string>
<string name="default_user_icon_description" msgid="6554047177298972638">"Erabiltzaile lehenetsiaren ikonoa"</string>
+ <!-- no translation found for physical_keyboard_title (4811935435315835220) -->
+ <skip />
+ <!-- no translation found for keyboard_layout_dialog_title (3927180147005616290) -->
+ <skip />
+ <!-- no translation found for keyboard_layout_default_label (1997292217218546957) -->
+ <skip />
</resources>
diff --git a/packages/SettingsLib/res/values-fa/strings.xml b/packages/SettingsLib/res/values-fa/strings.xml
index 5e7ee60..c50d247 100644
--- a/packages/SettingsLib/res/values-fa/strings.xml
+++ b/packages/SettingsLib/res/values-fa/strings.xml
@@ -533,6 +533,8 @@
<string name="accessibility_manual_zen_less_time" msgid="6828877595848229965">"زمان کمتر."</string>
<string name="cancel" msgid="5665114069455378395">"لغو"</string>
<string name="okay" msgid="949938843324579502">"تأیید"</string>
+ <!-- no translation found for done (381184316122520313) -->
+ <skip />
<string name="alarms_and_reminders_label" msgid="6918395649731424294">"زنگهای هشدار و یادآوریها"</string>
<string name="alarms_and_reminders_switch_title" msgid="4939393911531826222">"مجاز کردن تنظیم زنگ ساعت و یادآوری"</string>
<string name="alarms_and_reminders_title" msgid="8819933264635406032">"زنگهای ساعت و یادآوریها"</string>
@@ -551,7 +553,9 @@
<string name="zen_mode_duration_always_prompt_title" msgid="3212996860498119555">"هربار پرسیده شود"</string>
<string name="zen_mode_forever" msgid="3339224497605461291">"تا زمانیکه آن را خاموش کنید"</string>
<string name="time_unit_just_now" msgid="3006134267292728099">"هماکنون"</string>
- <string name="media_transfer_this_device_name" msgid="2357329267148436433">"این تلفن"</string>
+ <string name="media_transfer_this_device_name" product="default" msgid="2357329267148436433">"این تلفن"</string>
+ <!-- no translation found for media_transfer_this_device_name (3714653244000242800) -->
+ <skip />
<string name="media_transfer_this_phone" msgid="7194341457812151531">"این تلفن"</string>
<string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"مشکل در اتصال. دستگاه را خاموش و دوباره روشن کنید"</string>
<string name="media_transfer_wired_device_name" msgid="4447880899964056007">"دستگاه صوتی سیمی"</string>
@@ -591,7 +595,9 @@
<string name="user_set_lock_button" msgid="1427128184982594856">"تنظیم قفل"</string>
<string name="user_switch_to_user" msgid="6975428297154968543">"رفتن به <xliff:g id="USER_NAME">%s</xliff:g>"</string>
<string name="creating_new_user_dialog_message" msgid="7232880257538970375">"درحال ایجاد کاربر جدید…"</string>
+ <string name="creating_new_guest_dialog_message" msgid="1114905602181350690">"درحال ایجاد مهمان جدید…"</string>
<string name="add_user_failed" msgid="4809887794313944872">"کاربر جدید ایجاد نشد"</string>
+ <string name="add_guest_failed" msgid="8074548434469843443">"مهمان جدید ایجاد نشد"</string>
<string name="user_nickname" msgid="262624187455825083">"نام مستعار"</string>
<string name="guest_new_guest" msgid="3482026122932643557">"افزودن مهمان"</string>
<string name="guest_exit_guest" msgid="5908239569510734136">"حذف مهمان"</string>
@@ -644,4 +650,7 @@
<string name="dream_complication_title_cast_info" msgid="4038776652841885084">"اطلاعات ارسال محتوا"</string>
<string name="avatar_picker_title" msgid="8492884172713170652">"انتخاب عکس نمایه"</string>
<string name="default_user_icon_description" msgid="6554047177298972638">"نماد کاربر پیشفرض"</string>
+ <string name="physical_keyboard_title" msgid="4811935435315835220">"صفحهکلید فیزیکی"</string>
+ <string name="keyboard_layout_dialog_title" msgid="3927180147005616290">"انتخاب طرحبندی صفحهکلید"</string>
+ <string name="keyboard_layout_default_label" msgid="1997292217218546957">"پیشفرض"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-fi/strings.xml b/packages/SettingsLib/res/values-fi/strings.xml
index 04df99f..d958b81 100644
--- a/packages/SettingsLib/res/values-fi/strings.xml
+++ b/packages/SettingsLib/res/values-fi/strings.xml
@@ -533,6 +533,8 @@
<string name="accessibility_manual_zen_less_time" msgid="6828877595848229965">"Vähemmän aikaa"</string>
<string name="cancel" msgid="5665114069455378395">"Peru"</string>
<string name="okay" msgid="949938843324579502">"OK"</string>
+ <!-- no translation found for done (381184316122520313) -->
+ <skip />
<string name="alarms_and_reminders_label" msgid="6918395649731424294">"Herätykset ja muistutukset"</string>
<string name="alarms_and_reminders_switch_title" msgid="4939393911531826222">"Salli herätysten ja muistutusten lisääminen"</string>
<string name="alarms_and_reminders_title" msgid="8819933264635406032">"Herätykset ja muistutukset"</string>
@@ -551,7 +553,9 @@
<string name="zen_mode_duration_always_prompt_title" msgid="3212996860498119555">"Kysy aina"</string>
<string name="zen_mode_forever" msgid="3339224497605461291">"Kunnes laitat pois päältä"</string>
<string name="time_unit_just_now" msgid="3006134267292728099">"Äsken"</string>
- <string name="media_transfer_this_device_name" msgid="2357329267148436433">"Tämä puhelin"</string>
+ <string name="media_transfer_this_device_name" product="default" msgid="2357329267148436433">"Tämä puhelin"</string>
+ <!-- no translation found for media_transfer_this_device_name (3714653244000242800) -->
+ <skip />
<string name="media_transfer_this_phone" msgid="7194341457812151531">"Tämä puhelin"</string>
<string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"Yhteysvirhe. Sammuta laite ja käynnistä se uudelleen."</string>
<string name="media_transfer_wired_device_name" msgid="4447880899964056007">"Langallinen äänilaite"</string>
@@ -591,7 +595,9 @@
<string name="user_set_lock_button" msgid="1427128184982594856">"Aseta lukitus"</string>
<string name="user_switch_to_user" msgid="6975428297154968543">"Vaihda tähän käyttäjään: <xliff:g id="USER_NAME">%s</xliff:g>"</string>
<string name="creating_new_user_dialog_message" msgid="7232880257538970375">"Luodaan uutta käyttäjää…"</string>
+ <string name="creating_new_guest_dialog_message" msgid="1114905602181350690">"Luodaan uutta vierasta…"</string>
<string name="add_user_failed" msgid="4809887794313944872">"Uuden käyttäjän luominen epäonnistui"</string>
+ <string name="add_guest_failed" msgid="8074548434469843443">"Uutta vierasta ei voitu luoda"</string>
<string name="user_nickname" msgid="262624187455825083">"Lempinimi"</string>
<string name="guest_new_guest" msgid="3482026122932643557">"Lisää vieras"</string>
<string name="guest_exit_guest" msgid="5908239569510734136">"Poista vieras"</string>
@@ -644,4 +650,7 @@
<string name="dream_complication_title_cast_info" msgid="4038776652841885084">"Striimaustiedot"</string>
<string name="avatar_picker_title" msgid="8492884172713170652">"Valitse profiilikuva"</string>
<string name="default_user_icon_description" msgid="6554047177298972638">"Oletuskäyttäjäkuvake"</string>
+ <string name="physical_keyboard_title" msgid="4811935435315835220">"Fyysinen näppäimistö"</string>
+ <string name="keyboard_layout_dialog_title" msgid="3927180147005616290">"Valitse näppäimistöasettelu"</string>
+ <string name="keyboard_layout_default_label" msgid="1997292217218546957">"Oletus"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-fr-rCA/strings.xml b/packages/SettingsLib/res/values-fr-rCA/strings.xml
index 88ddd28..4999bda 100644
--- a/packages/SettingsLib/res/values-fr-rCA/strings.xml
+++ b/packages/SettingsLib/res/values-fr-rCA/strings.xml
@@ -533,6 +533,8 @@
<string name="accessibility_manual_zen_less_time" msgid="6828877595848229965">"Moins longtemps."</string>
<string name="cancel" msgid="5665114069455378395">"Annuler"</string>
<string name="okay" msgid="949938843324579502">"OK"</string>
+ <!-- no translation found for done (381184316122520313) -->
+ <skip />
<string name="alarms_and_reminders_label" msgid="6918395649731424294">"Alarmes et rappels"</string>
<string name="alarms_and_reminders_switch_title" msgid="4939393911531826222">"Autoriser la création d\'alarmes et de rappels"</string>
<string name="alarms_and_reminders_title" msgid="8819933264635406032">"Alarmes et rappels"</string>
@@ -551,7 +553,9 @@
<string name="zen_mode_duration_always_prompt_title" msgid="3212996860498119555">"Toujours demander"</string>
<string name="zen_mode_forever" msgid="3339224497605461291">"Jusqu\'à la désactivation"</string>
<string name="time_unit_just_now" msgid="3006134267292728099">"À l\'instant"</string>
- <string name="media_transfer_this_device_name" msgid="2357329267148436433">"Ce téléphone"</string>
+ <string name="media_transfer_this_device_name" product="default" msgid="2357329267148436433">"Ce téléphone"</string>
+ <!-- no translation found for media_transfer_this_device_name (3714653244000242800) -->
+ <skip />
<string name="media_transfer_this_phone" msgid="7194341457812151531">"Ce téléphone"</string>
<string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"Problème de connexion. Éteingez et rallumez l\'appareil"</string>
<string name="media_transfer_wired_device_name" msgid="4447880899964056007">"Appareil audio à câble"</string>
@@ -591,7 +595,9 @@
<string name="user_set_lock_button" msgid="1427128184982594856">"Définir verrouillage écran"</string>
<string name="user_switch_to_user" msgid="6975428297154968543">"Passer à <xliff:g id="USER_NAME">%s</xliff:g>"</string>
<string name="creating_new_user_dialog_message" msgid="7232880257538970375">"Création d\'un utilisateur en cours…"</string>
+ <string name="creating_new_guest_dialog_message" msgid="1114905602181350690">"Création d\'un nouvel invité en cours…"</string>
<string name="add_user_failed" msgid="4809887794313944872">"Impossible de créer un utilisateur"</string>
+ <string name="add_guest_failed" msgid="8074548434469843443">"Impossible de créer un nouvel invité"</string>
<string name="user_nickname" msgid="262624187455825083">"Pseudo"</string>
<string name="guest_new_guest" msgid="3482026122932643557">"Ajouter un invité"</string>
<string name="guest_exit_guest" msgid="5908239569510734136">"Supprimer l\'invité"</string>
@@ -644,4 +650,10 @@
<string name="dream_complication_title_cast_info" msgid="4038776652841885084">"Info diffusion"</string>
<string name="avatar_picker_title" msgid="8492884172713170652">"Choisir une photo de profil"</string>
<string name="default_user_icon_description" msgid="6554047177298972638">"Icône d\'utilisateur par défaut"</string>
+ <!-- no translation found for physical_keyboard_title (4811935435315835220) -->
+ <skip />
+ <!-- no translation found for keyboard_layout_dialog_title (3927180147005616290) -->
+ <skip />
+ <!-- no translation found for keyboard_layout_default_label (1997292217218546957) -->
+ <skip />
</resources>
diff --git a/packages/SettingsLib/res/values-fr/strings.xml b/packages/SettingsLib/res/values-fr/strings.xml
index c703484..5257534 100644
--- a/packages/SettingsLib/res/values-fr/strings.xml
+++ b/packages/SettingsLib/res/values-fr/strings.xml
@@ -533,6 +533,8 @@
<string name="accessibility_manual_zen_less_time" msgid="6828877595848229965">"Moins longtemps."</string>
<string name="cancel" msgid="5665114069455378395">"Annuler"</string>
<string name="okay" msgid="949938843324579502">"OK"</string>
+ <!-- no translation found for done (381184316122520313) -->
+ <skip />
<string name="alarms_and_reminders_label" msgid="6918395649731424294">"Alarmes et rappels"</string>
<string name="alarms_and_reminders_switch_title" msgid="4939393911531826222">"Autoriser à définir des alarmes et des rappels"</string>
<string name="alarms_and_reminders_title" msgid="8819933264635406032">"Alarmes et rappels"</string>
@@ -551,7 +553,9 @@
<string name="zen_mode_duration_always_prompt_title" msgid="3212996860498119555">"Toujours demander"</string>
<string name="zen_mode_forever" msgid="3339224497605461291">"Jusqu\'à la désactivation"</string>
<string name="time_unit_just_now" msgid="3006134267292728099">"À l\'instant"</string>
- <string name="media_transfer_this_device_name" msgid="2357329267148436433">"Ce téléphone"</string>
+ <string name="media_transfer_this_device_name" product="default" msgid="2357329267148436433">"Ce téléphone"</string>
+ <!-- no translation found for media_transfer_this_device_name (3714653244000242800) -->
+ <skip />
<string name="media_transfer_this_phone" msgid="7194341457812151531">"Ce téléphone"</string>
<string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"Problème de connexion. Éteignez l\'appareil, puis rallumez-le"</string>
<string name="media_transfer_wired_device_name" msgid="4447880899964056007">"Appareil audio filaire"</string>
@@ -591,7 +595,9 @@
<string name="user_set_lock_button" msgid="1427128184982594856">"Définir verrouillage écran"</string>
<string name="user_switch_to_user" msgid="6975428297154968543">"Passer à <xliff:g id="USER_NAME">%s</xliff:g>"</string>
<string name="creating_new_user_dialog_message" msgid="7232880257538970375">"Création d\'un nouvel utilisateur…"</string>
+ <string name="creating_new_guest_dialog_message" msgid="1114905602181350690">"Création du profil invité…"</string>
<string name="add_user_failed" msgid="4809887794313944872">"Échec de la création d\'un utilisateur"</string>
+ <string name="add_guest_failed" msgid="8074548434469843443">"Impossible de créer un profil invité"</string>
<string name="user_nickname" msgid="262624187455825083">"Pseudo"</string>
<string name="guest_new_guest" msgid="3482026122932643557">"Ajouter un invité"</string>
<string name="guest_exit_guest" msgid="5908239569510734136">"Supprimer l\'invité"</string>
@@ -644,4 +650,10 @@
<string name="dream_complication_title_cast_info" msgid="4038776652841885084">"Infos distribution"</string>
<string name="avatar_picker_title" msgid="8492884172713170652">"Choisissez une photo de profil"</string>
<string name="default_user_icon_description" msgid="6554047177298972638">"Icône de l\'utilisateur par défaut"</string>
+ <!-- no translation found for physical_keyboard_title (4811935435315835220) -->
+ <skip />
+ <!-- no translation found for keyboard_layout_dialog_title (3927180147005616290) -->
+ <skip />
+ <!-- no translation found for keyboard_layout_default_label (1997292217218546957) -->
+ <skip />
</resources>
diff --git a/packages/SettingsLib/res/values-gl/strings.xml b/packages/SettingsLib/res/values-gl/strings.xml
index 02fa931f..f45c60d 100644
--- a/packages/SettingsLib/res/values-gl/strings.xml
+++ b/packages/SettingsLib/res/values-gl/strings.xml
@@ -533,6 +533,8 @@
<string name="accessibility_manual_zen_less_time" msgid="6828877595848229965">"Menos tempo."</string>
<string name="cancel" msgid="5665114069455378395">"Cancelar"</string>
<string name="okay" msgid="949938843324579502">"Aceptar"</string>
+ <!-- no translation found for done (381184316122520313) -->
+ <skip />
<string name="alarms_and_reminders_label" msgid="6918395649731424294">"Alarmas e recordatorios"</string>
<string name="alarms_and_reminders_switch_title" msgid="4939393911531826222">"Permitir axuste de alarmas e recordatorios"</string>
<string name="alarms_and_reminders_title" msgid="8819933264635406032">"Alarmas e recordatorios"</string>
@@ -551,7 +553,9 @@
<string name="zen_mode_duration_always_prompt_title" msgid="3212996860498119555">"Preguntar sempre"</string>
<string name="zen_mode_forever" msgid="3339224497605461291">"Ata a desactivación"</string>
<string name="time_unit_just_now" msgid="3006134267292728099">"Agora mesmo"</string>
- <string name="media_transfer_this_device_name" msgid="2357329267148436433">"Este teléfono"</string>
+ <string name="media_transfer_this_device_name" product="default" msgid="2357329267148436433">"Este teléfono"</string>
+ <!-- no translation found for media_transfer_this_device_name (3714653244000242800) -->
+ <skip />
<string name="media_transfer_this_phone" msgid="7194341457812151531">"Este teléfono"</string>
<string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"Produciuse un problema coa conexión. Apaga e acende o dispositivo."</string>
<string name="media_transfer_wired_device_name" msgid="4447880899964056007">"Dispositivo de audio con cable"</string>
@@ -591,7 +595,9 @@
<string name="user_set_lock_button" msgid="1427128184982594856">"Establecer bloqueo"</string>
<string name="user_switch_to_user" msgid="6975428297154968543">"Cambiar a <xliff:g id="USER_NAME">%s</xliff:g>"</string>
<string name="creating_new_user_dialog_message" msgid="7232880257538970375">"Creando usuario novo…"</string>
+ <string name="creating_new_guest_dialog_message" msgid="1114905602181350690">"Creando novo convidado…"</string>
<string name="add_user_failed" msgid="4809887794313944872">"Non se puido crear un novo usuario"</string>
+ <string name="add_guest_failed" msgid="8074548434469843443">"Produciuse un erro ao crear o convidado"</string>
<string name="user_nickname" msgid="262624187455825083">"Alcume"</string>
<string name="guest_new_guest" msgid="3482026122932643557">"Engadir convidado"</string>
<string name="guest_exit_guest" msgid="5908239569510734136">"Quitar convidado"</string>
@@ -644,4 +650,10 @@
<string name="dream_complication_title_cast_info" msgid="4038776652841885084">"Datos da emisión"</string>
<string name="avatar_picker_title" msgid="8492884172713170652">"Escolle unha imaxe do perfil"</string>
<string name="default_user_icon_description" msgid="6554047177298972638">"Icona do usuario predeterminado"</string>
+ <!-- no translation found for physical_keyboard_title (4811935435315835220) -->
+ <skip />
+ <!-- no translation found for keyboard_layout_dialog_title (3927180147005616290) -->
+ <skip />
+ <!-- no translation found for keyboard_layout_default_label (1997292217218546957) -->
+ <skip />
</resources>
diff --git a/packages/SettingsLib/res/values-gu/strings.xml b/packages/SettingsLib/res/values-gu/strings.xml
index b2a9ff3..672bd77 100644
--- a/packages/SettingsLib/res/values-gu/strings.xml
+++ b/packages/SettingsLib/res/values-gu/strings.xml
@@ -533,6 +533,8 @@
<string name="accessibility_manual_zen_less_time" msgid="6828877595848229965">"ઓછો સમય."</string>
<string name="cancel" msgid="5665114069455378395">"રદ કરો"</string>
<string name="okay" msgid="949938843324579502">"ઓકે"</string>
+ <!-- no translation found for done (381184316122520313) -->
+ <skip />
<string name="alarms_and_reminders_label" msgid="6918395649731424294">"અલાર્મ અને રિમાઇન્ડર"</string>
<string name="alarms_and_reminders_switch_title" msgid="4939393911531826222">"અલાર્મ અને રિમાન્ડરના સેટિંગની મંજૂરી આપો"</string>
<string name="alarms_and_reminders_title" msgid="8819933264635406032">"અલાર્મ અને રિમાઇન્ડર"</string>
@@ -551,7 +553,9 @@
<string name="zen_mode_duration_always_prompt_title" msgid="3212996860498119555">"દર વખતે પૂછો"</string>
<string name="zen_mode_forever" msgid="3339224497605461291">"તમે બંધ ન કરો ત્યાં સુધી"</string>
<string name="time_unit_just_now" msgid="3006134267292728099">"હમણાં જ"</string>
- <string name="media_transfer_this_device_name" msgid="2357329267148436433">"આ ફોન"</string>
+ <string name="media_transfer_this_device_name" product="default" msgid="2357329267148436433">"આ ફોન"</string>
+ <!-- no translation found for media_transfer_this_device_name (3714653244000242800) -->
+ <skip />
<string name="media_transfer_this_phone" msgid="7194341457812151531">"આ ફોન"</string>
<string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"કનેક્ટ કરવામાં સમસ્યા આવી રહી છે. ડિવાઇસને બંધ કરીને ફરી ચાલુ કરો"</string>
<string name="media_transfer_wired_device_name" msgid="4447880899964056007">"વાયરવાળો ઑડિયો ડિવાઇસ"</string>
@@ -591,7 +595,9 @@
<string name="user_set_lock_button" msgid="1427128184982594856">"લૉક સેટ કરો"</string>
<string name="user_switch_to_user" msgid="6975428297154968543">"<xliff:g id="USER_NAME">%s</xliff:g> પર સ્વિચ કરો"</string>
<string name="creating_new_user_dialog_message" msgid="7232880257538970375">"નવા વપરાશકર્તા બનાવી રહ્યાં છીએ…"</string>
+ <string name="creating_new_guest_dialog_message" msgid="1114905602181350690">"નવા અતિથિની પ્રોફાઇલ બનાવી રહ્યાં છીએ…"</string>
<string name="add_user_failed" msgid="4809887794313944872">"નવો વપરાશકર્તા બનાવવામાં નિષ્ફળ"</string>
+ <string name="add_guest_failed" msgid="8074548434469843443">"નવી અતિથિ બનાવવામાં નિષ્ફળ રહ્યાં"</string>
<string name="user_nickname" msgid="262624187455825083">"ઉપનામ"</string>
<string name="guest_new_guest" msgid="3482026122932643557">"અતિથિ ઉમેરો"</string>
<string name="guest_exit_guest" msgid="5908239569510734136">"અતિથિને કાઢી નાખો"</string>
@@ -644,4 +650,7 @@
<string name="dream_complication_title_cast_info" msgid="4038776652841885084">"કાસ્ટ વિશેની માહિતી"</string>
<string name="avatar_picker_title" msgid="8492884172713170652">"પ્રોફાઇલ ફોટો પસંદ કરો"</string>
<string name="default_user_icon_description" msgid="6554047177298972638">"ડિફૉલ્ટ વપરાશકર્તાનું આઇકન"</string>
+ <string name="physical_keyboard_title" msgid="4811935435315835220">"ભૌતિક કીબોર્ડ"</string>
+ <string name="keyboard_layout_dialog_title" msgid="3927180147005616290">"કીબોર્ડ લેઆઉટ પસંદ કરો"</string>
+ <string name="keyboard_layout_default_label" msgid="1997292217218546957">"ડિફૉલ્ટ"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-hi/strings.xml b/packages/SettingsLib/res/values-hi/strings.xml
index fa51dd2..55e3eaf 100644
--- a/packages/SettingsLib/res/values-hi/strings.xml
+++ b/packages/SettingsLib/res/values-hi/strings.xml
@@ -533,6 +533,8 @@
<string name="accessibility_manual_zen_less_time" msgid="6828877595848229965">"कम समय."</string>
<string name="cancel" msgid="5665114069455378395">"रद्द करें"</string>
<string name="okay" msgid="949938843324579502">"ठीक है"</string>
+ <!-- no translation found for done (381184316122520313) -->
+ <skip />
<string name="alarms_and_reminders_label" msgid="6918395649731424294">"अलार्म और रिमाइंडर"</string>
<string name="alarms_and_reminders_switch_title" msgid="4939393911531826222">"अलार्म और रिमाइंडर सेट करने की अनुमति दें"</string>
<string name="alarms_and_reminders_title" msgid="8819933264635406032">"अलार्म और रिमाइंडर"</string>
@@ -551,7 +553,9 @@
<string name="zen_mode_duration_always_prompt_title" msgid="3212996860498119555">"हर बार पूछें"</string>
<string name="zen_mode_forever" msgid="3339224497605461291">"जब तक आप इसे बंद नहीं करते"</string>
<string name="time_unit_just_now" msgid="3006134267292728099">"अभी-अभी"</string>
- <string name="media_transfer_this_device_name" msgid="2357329267148436433">"यह फ़ोन"</string>
+ <string name="media_transfer_this_device_name" product="default" msgid="2357329267148436433">"यह फ़ोन"</string>
+ <!-- no translation found for media_transfer_this_device_name (3714653244000242800) -->
+ <skip />
<string name="media_transfer_this_phone" msgid="7194341457812151531">"यह फ़ोन"</string>
<string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"कनेक्ट करने में समस्या हो रही है. डिवाइस को बंद करके चालू करें"</string>
<string name="media_transfer_wired_device_name" msgid="4447880899964056007">"वायर वाला ऑडियो डिवाइस"</string>
@@ -591,7 +595,9 @@
<string name="user_set_lock_button" msgid="1427128184982594856">"लॉक सेट करें"</string>
<string name="user_switch_to_user" msgid="6975428297154968543">"<xliff:g id="USER_NAME">%s</xliff:g> पर जाएं"</string>
<string name="creating_new_user_dialog_message" msgid="7232880257538970375">"नया उपयोगकर्ता बनाया जा रहा है…"</string>
+ <string name="creating_new_guest_dialog_message" msgid="1114905602181350690">"नया मेहमान खाता बनाया जा रहा है…"</string>
<string name="add_user_failed" msgid="4809887794313944872">"नया उपयोगकर्ता जोड़ा नहीं जा सका"</string>
+ <string name="add_guest_failed" msgid="8074548434469843443">"नया मेहमान खाता नहीं बनाया जा सका"</string>
<string name="user_nickname" msgid="262624187455825083">"प्रचलित नाम"</string>
<string name="guest_new_guest" msgid="3482026122932643557">"मेहमान जोड़ें"</string>
<string name="guest_exit_guest" msgid="5908239569510734136">"मेहमान हटाएं"</string>
@@ -644,4 +650,7 @@
<string name="dream_complication_title_cast_info" msgid="4038776652841885084">"कास्टिंग की जानकारी"</string>
<string name="avatar_picker_title" msgid="8492884172713170652">"प्रोफ़ाइल फ़ोटो चुनें"</string>
<string name="default_user_icon_description" msgid="6554047177298972638">"उपयोगकर्ता के लिए डिफ़ॉल्ट आइकॉन"</string>
+ <string name="physical_keyboard_title" msgid="4811935435315835220">"फ़िज़िकल कीबोर्ड"</string>
+ <string name="keyboard_layout_dialog_title" msgid="3927180147005616290">"कीबोर्ड का लेआउट चुनें"</string>
+ <string name="keyboard_layout_default_label" msgid="1997292217218546957">"डिफ़ॉल्ट"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-hr/strings.xml b/packages/SettingsLib/res/values-hr/strings.xml
index 12d9745..fd29bb5 100644
--- a/packages/SettingsLib/res/values-hr/strings.xml
+++ b/packages/SettingsLib/res/values-hr/strings.xml
@@ -533,6 +533,8 @@
<string name="accessibility_manual_zen_less_time" msgid="6828877595848229965">"Manje vremena."</string>
<string name="cancel" msgid="5665114069455378395">"Odustani"</string>
<string name="okay" msgid="949938843324579502">"U redu"</string>
+ <!-- no translation found for done (381184316122520313) -->
+ <skip />
<string name="alarms_and_reminders_label" msgid="6918395649731424294">"Alarmi i podsjetnici"</string>
<string name="alarms_and_reminders_switch_title" msgid="4939393911531826222">"Dopusti postavljanje alarma i podsjetnika"</string>
<string name="alarms_and_reminders_title" msgid="8819933264635406032">"Alarmi i podsjetnici"</string>
@@ -551,7 +553,9 @@
<string name="zen_mode_duration_always_prompt_title" msgid="3212996860498119555">"Pitaj svaki put"</string>
<string name="zen_mode_forever" msgid="3339224497605461291">"Dok ne isključite"</string>
<string name="time_unit_just_now" msgid="3006134267292728099">"Upravo sad"</string>
- <string name="media_transfer_this_device_name" msgid="2357329267148436433">"Ovaj telefon"</string>
+ <string name="media_transfer_this_device_name" product="default" msgid="2357329267148436433">"Ovaj telefon"</string>
+ <!-- no translation found for media_transfer_this_device_name (3714653244000242800) -->
+ <skip />
<string name="media_transfer_this_phone" msgid="7194341457812151531">"Ovaj telefon"</string>
<string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"Problem s povezivanjem. Isključite i ponovo uključite uređaj"</string>
<string name="media_transfer_wired_device_name" msgid="4447880899964056007">"Žičani audiouređaj"</string>
@@ -591,7 +595,9 @@
<string name="user_set_lock_button" msgid="1427128184982594856">"Postavi zaključavanje"</string>
<string name="user_switch_to_user" msgid="6975428297154968543">"Prelazak na korisnika <xliff:g id="USER_NAME">%s</xliff:g>"</string>
<string name="creating_new_user_dialog_message" msgid="7232880257538970375">"Izrada novog korisnika…"</string>
+ <string name="creating_new_guest_dialog_message" msgid="1114905602181350690">"Izrada novog gosta…"</string>
<string name="add_user_failed" msgid="4809887794313944872">"Izrada novog korisnika nije uspjela"</string>
+ <string name="add_guest_failed" msgid="8074548434469843443">"Izrada novog gosta nije uspjela"</string>
<string name="user_nickname" msgid="262624187455825083">"Nadimak"</string>
<string name="guest_new_guest" msgid="3482026122932643557">"Dodavanje gosta"</string>
<string name="guest_exit_guest" msgid="5908239569510734136">"Uklanjanje gosta"</string>
@@ -644,4 +650,10 @@
<string name="dream_complication_title_cast_info" msgid="4038776652841885084">"Inform. o emitiranju"</string>
<string name="avatar_picker_title" msgid="8492884172713170652">"Odabir profilne slike"</string>
<string name="default_user_icon_description" msgid="6554047177298972638">"Ikona zadanog korisnika"</string>
+ <!-- no translation found for physical_keyboard_title (4811935435315835220) -->
+ <skip />
+ <!-- no translation found for keyboard_layout_dialog_title (3927180147005616290) -->
+ <skip />
+ <!-- no translation found for keyboard_layout_default_label (1997292217218546957) -->
+ <skip />
</resources>
diff --git a/packages/SettingsLib/res/values-hu/strings.xml b/packages/SettingsLib/res/values-hu/strings.xml
index 984df4a..dae5854 100644
--- a/packages/SettingsLib/res/values-hu/strings.xml
+++ b/packages/SettingsLib/res/values-hu/strings.xml
@@ -533,6 +533,8 @@
<string name="accessibility_manual_zen_less_time" msgid="6828877595848229965">"Kevesebb idő."</string>
<string name="cancel" msgid="5665114069455378395">"Mégse"</string>
<string name="okay" msgid="949938843324579502">"OK"</string>
+ <!-- no translation found for done (381184316122520313) -->
+ <skip />
<string name="alarms_and_reminders_label" msgid="6918395649731424294">"Ébresztések és emlékeztetők"</string>
<string name="alarms_and_reminders_switch_title" msgid="4939393911531826222">"Beállíthat ébresztéseket és emlékeztetőket"</string>
<string name="alarms_and_reminders_title" msgid="8819933264635406032">"Ébresztések és emlékeztetők"</string>
@@ -551,7 +553,9 @@
<string name="zen_mode_duration_always_prompt_title" msgid="3212996860498119555">"Mindig kérdezzen rá"</string>
<string name="zen_mode_forever" msgid="3339224497605461291">"Kikapcsolásig"</string>
<string name="time_unit_just_now" msgid="3006134267292728099">"Az imént"</string>
- <string name="media_transfer_this_device_name" msgid="2357329267148436433">"Ez a telefon"</string>
+ <string name="media_transfer_this_device_name" product="default" msgid="2357329267148436433">"Ez a telefon"</string>
+ <!-- no translation found for media_transfer_this_device_name (3714653244000242800) -->
+ <skip />
<string name="media_transfer_this_phone" msgid="7194341457812151531">"Ez a telefon"</string>
<string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"Sikertelen csatlakozás. Kapcsolja ki az eszközt, majd kapcsolja be újra."</string>
<string name="media_transfer_wired_device_name" msgid="4447880899964056007">"Vezetékes audioeszköz"</string>
@@ -591,7 +595,9 @@
<string name="user_set_lock_button" msgid="1427128184982594856">"Képernyőzár beállítása"</string>
<string name="user_switch_to_user" msgid="6975428297154968543">"Váltás erre: <xliff:g id="USER_NAME">%s</xliff:g>"</string>
<string name="creating_new_user_dialog_message" msgid="7232880257538970375">"Új felhasználó létrehozása…"</string>
+ <string name="creating_new_guest_dialog_message" msgid="1114905602181350690">"Új vendég létrehozása…"</string>
<string name="add_user_failed" msgid="4809887794313944872">"Az új felhasználó létrehozása sikertelen"</string>
+ <string name="add_guest_failed" msgid="8074548434469843443">"Az új vendég létrehozása nem sikerült"</string>
<string name="user_nickname" msgid="262624187455825083">"Becenév"</string>
<string name="guest_new_guest" msgid="3482026122932643557">"Vendég hozzáadása"</string>
<string name="guest_exit_guest" msgid="5908239569510734136">"Vendég munkamenet eltávolítása"</string>
@@ -644,4 +650,7 @@
<string name="dream_complication_title_cast_info" msgid="4038776652841885084">"Átküldési információ"</string>
<string name="avatar_picker_title" msgid="8492884172713170652">"Profilkép választása"</string>
<string name="default_user_icon_description" msgid="6554047177298972638">"Alapértelmezett felhasználó ikonja"</string>
+ <string name="physical_keyboard_title" msgid="4811935435315835220">"Fizikai billentyűzet"</string>
+ <string name="keyboard_layout_dialog_title" msgid="3927180147005616290">"Billentyűzetkiosztás kiválasztása"</string>
+ <string name="keyboard_layout_default_label" msgid="1997292217218546957">"Alapértelmezett"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-hy/strings.xml b/packages/SettingsLib/res/values-hy/strings.xml
index 1488aea..61d9093 100644
--- a/packages/SettingsLib/res/values-hy/strings.xml
+++ b/packages/SettingsLib/res/values-hy/strings.xml
@@ -533,6 +533,8 @@
<string name="accessibility_manual_zen_less_time" msgid="6828877595848229965">"Պակասեցնել ժամանակը:"</string>
<string name="cancel" msgid="5665114069455378395">"Չեղարկել"</string>
<string name="okay" msgid="949938843324579502">"Եղավ"</string>
+ <!-- no translation found for done (381184316122520313) -->
+ <skip />
<string name="alarms_and_reminders_label" msgid="6918395649731424294">"Զարթուցիչներ և հիշեցումներ"</string>
<string name="alarms_and_reminders_switch_title" msgid="4939393911531826222">"Թույլատրել զարթուցիչների և հիշեցումների սահմանումը"</string>
<string name="alarms_and_reminders_title" msgid="8819933264635406032">"Զարթուցիչներ և հիշեցումներ"</string>
@@ -551,7 +553,9 @@
<string name="zen_mode_duration_always_prompt_title" msgid="3212996860498119555">"Ամեն անգամ հարցնել"</string>
<string name="zen_mode_forever" msgid="3339224497605461291">"Մինչև անջատեք"</string>
<string name="time_unit_just_now" msgid="3006134267292728099">"Հենց նոր"</string>
- <string name="media_transfer_this_device_name" msgid="2357329267148436433">"Այս հեռախոսը"</string>
+ <string name="media_transfer_this_device_name" product="default" msgid="2357329267148436433">"Այս հեռախոսը"</string>
+ <!-- no translation found for media_transfer_this_device_name (3714653244000242800) -->
+ <skip />
<string name="media_transfer_this_phone" msgid="7194341457812151531">"Այս հեռախոսը"</string>
<string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"Կապի խնդիր կա: Սարքն անջատեք և նորից միացրեք:"</string>
<string name="media_transfer_wired_device_name" msgid="4447880899964056007">"Լարով աուդիո սարք"</string>
@@ -591,7 +595,9 @@
<string name="user_set_lock_button" msgid="1427128184982594856">"Կարգավորել կողպումը"</string>
<string name="user_switch_to_user" msgid="6975428297154968543">"Անցնել <xliff:g id="USER_NAME">%s</xliff:g> պրոֆիլին"</string>
<string name="creating_new_user_dialog_message" msgid="7232880257538970375">"Ստեղծվում է օգտատիրոջ նոր պրոֆիլ…"</string>
+ <string name="creating_new_guest_dialog_message" msgid="1114905602181350690">"Նոր հյուրի ստեղծում…"</string>
<string name="add_user_failed" msgid="4809887794313944872">"Չհաջողվեց ստեղծել նոր օգտատեր"</string>
+ <string name="add_guest_failed" msgid="8074548434469843443">"Չհաջողվեց նոր հյուր ստեղծել"</string>
<string name="user_nickname" msgid="262624187455825083">"Կեղծանուն"</string>
<string name="guest_new_guest" msgid="3482026122932643557">"Ավելացնել հյուր"</string>
<string name="guest_exit_guest" msgid="5908239569510734136">"Հեռացնել հյուրին"</string>
@@ -644,4 +650,7 @@
<string name="dream_complication_title_cast_info" msgid="4038776652841885084">"Հեռարձակման տվյալներ"</string>
<string name="avatar_picker_title" msgid="8492884172713170652">"Պրոֆիլի նկար ընտրեք"</string>
<string name="default_user_icon_description" msgid="6554047177298972638">"Օգտատիրոջ կանխադրված պատկերակ"</string>
+ <string name="physical_keyboard_title" msgid="4811935435315835220">"Ֆիզիկական ստեղնաշար"</string>
+ <string name="keyboard_layout_dialog_title" msgid="3927180147005616290">"Ընտրեք ստեղնաշարի դասավորությունը"</string>
+ <string name="keyboard_layout_default_label" msgid="1997292217218546957">"Կանխադրված"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-in/strings.xml b/packages/SettingsLib/res/values-in/strings.xml
index ffa4d4a..b60e0b7 100644
--- a/packages/SettingsLib/res/values-in/strings.xml
+++ b/packages/SettingsLib/res/values-in/strings.xml
@@ -533,6 +533,8 @@
<string name="accessibility_manual_zen_less_time" msgid="6828877595848229965">"Lebih cepat."</string>
<string name="cancel" msgid="5665114069455378395">"Batal"</string>
<string name="okay" msgid="949938843324579502">"Oke"</string>
+ <!-- no translation found for done (381184316122520313) -->
+ <skip />
<string name="alarms_and_reminders_label" msgid="6918395649731424294">"Alarm dan pengingat"</string>
<string name="alarms_and_reminders_switch_title" msgid="4939393911531826222">"Izinkan menyetel alarm dan pengingat"</string>
<string name="alarms_and_reminders_title" msgid="8819933264635406032">"Alarm & pengingat"</string>
@@ -551,7 +553,9 @@
<string name="zen_mode_duration_always_prompt_title" msgid="3212996860498119555">"Selalu tanya"</string>
<string name="zen_mode_forever" msgid="3339224497605461291">"Sampai Anda menonaktifkannya"</string>
<string name="time_unit_just_now" msgid="3006134267292728099">"Baru saja"</string>
- <string name="media_transfer_this_device_name" msgid="2357329267148436433">"Ponsel ini"</string>
+ <string name="media_transfer_this_device_name" product="default" msgid="2357329267148436433">"Ponsel ini"</string>
+ <!-- no translation found for media_transfer_this_device_name (3714653244000242800) -->
+ <skip />
<string name="media_transfer_this_phone" msgid="7194341457812151531">"Ponsel ini"</string>
<string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"Ada masalah saat menghubungkan. Nonaktifkan perangkat & aktifkan kembali"</string>
<string name="media_transfer_wired_device_name" msgid="4447880899964056007">"Perangkat audio berkabel"</string>
@@ -591,7 +595,9 @@
<string name="user_set_lock_button" msgid="1427128184982594856">"Setel kunci"</string>
<string name="user_switch_to_user" msgid="6975428297154968543">"Beralih ke <xliff:g id="USER_NAME">%s</xliff:g>"</string>
<string name="creating_new_user_dialog_message" msgid="7232880257538970375">"Membuat pengguna baru …"</string>
+ <string name="creating_new_guest_dialog_message" msgid="1114905602181350690">"Membuat tamu baru …"</string>
<string name="add_user_failed" msgid="4809887794313944872">"Gagal membuat pengguna baru"</string>
+ <string name="add_guest_failed" msgid="8074548434469843443">"Gagal membuat tamu baru"</string>
<string name="user_nickname" msgid="262624187455825083">"Nama panggilan"</string>
<string name="guest_new_guest" msgid="3482026122932643557">"Tambahkan tamu"</string>
<string name="guest_exit_guest" msgid="5908239569510734136">"Hapus tamu"</string>
@@ -644,4 +650,7 @@
<string name="dream_complication_title_cast_info" msgid="4038776652841885084">"Info Transmisi"</string>
<string name="avatar_picker_title" msgid="8492884172713170652">"Pilih foto profil"</string>
<string name="default_user_icon_description" msgid="6554047177298972638">"Ikon pengguna default"</string>
+ <string name="physical_keyboard_title" msgid="4811935435315835220">"Keyboard fisik"</string>
+ <string name="keyboard_layout_dialog_title" msgid="3927180147005616290">"Pilih tata letak keyboard"</string>
+ <string name="keyboard_layout_default_label" msgid="1997292217218546957">"Default"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-is/strings.xml b/packages/SettingsLib/res/values-is/strings.xml
index b8a75047..40724fd 100644
--- a/packages/SettingsLib/res/values-is/strings.xml
+++ b/packages/SettingsLib/res/values-is/strings.xml
@@ -533,6 +533,8 @@
<string name="accessibility_manual_zen_less_time" msgid="6828877595848229965">"Minni tími."</string>
<string name="cancel" msgid="5665114069455378395">"Hætta við"</string>
<string name="okay" msgid="949938843324579502">"Í lagi"</string>
+ <!-- no translation found for done (381184316122520313) -->
+ <skip />
<string name="alarms_and_reminders_label" msgid="6918395649731424294">"Vekjarar og áminningar"</string>
<string name="alarms_and_reminders_switch_title" msgid="4939393911531826222">"Leyfa stillingu vekjara og áminninga"</string>
<string name="alarms_and_reminders_title" msgid="8819933264635406032">"Vekjarar og áminningar"</string>
@@ -551,7 +553,9 @@
<string name="zen_mode_duration_always_prompt_title" msgid="3212996860498119555">"Spyrja í hvert skipti"</string>
<string name="zen_mode_forever" msgid="3339224497605461291">"Þar til þú slekkur"</string>
<string name="time_unit_just_now" msgid="3006134267292728099">"Rétt í þessu"</string>
- <string name="media_transfer_this_device_name" msgid="2357329267148436433">"Þessi sími"</string>
+ <string name="media_transfer_this_device_name" product="default" msgid="2357329267148436433">"Þessi sími"</string>
+ <!-- no translation found for media_transfer_this_device_name (3714653244000242800) -->
+ <skip />
<string name="media_transfer_this_phone" msgid="7194341457812151531">"Þessi sími"</string>
<string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"Vandamál í tengingu. Slökktu og kveiktu á tækinu"</string>
<string name="media_transfer_wired_device_name" msgid="4447880899964056007">"Snúrutengt hljómtæki"</string>
@@ -591,7 +595,9 @@
<string name="user_set_lock_button" msgid="1427128184982594856">"Velja lás"</string>
<string name="user_switch_to_user" msgid="6975428297154968543">"Skipta yfir í <xliff:g id="USER_NAME">%s</xliff:g>"</string>
<string name="creating_new_user_dialog_message" msgid="7232880257538970375">"Stofnar nýjan notanda…"</string>
+ <string name="creating_new_guest_dialog_message" msgid="1114905602181350690">"Býr til nýjan gest…"</string>
<string name="add_user_failed" msgid="4809887794313944872">"Ekki tókst að stofna nýjan notanda"</string>
+ <string name="add_guest_failed" msgid="8074548434469843443">"Ekki tókst að búa til nýjan gest"</string>
<string name="user_nickname" msgid="262624187455825083">"Gælunafn"</string>
<string name="guest_new_guest" msgid="3482026122932643557">"Bæta gesti við"</string>
<string name="guest_exit_guest" msgid="5908239569510734136">"Fjarlægja gest"</string>
@@ -644,4 +650,7 @@
<string name="dream_complication_title_cast_info" msgid="4038776652841885084">"Útsendingaruppl."</string>
<string name="avatar_picker_title" msgid="8492884172713170652">"Veldu prófílmynd"</string>
<string name="default_user_icon_description" msgid="6554047177298972638">"Tákn sjálfgefins notanda"</string>
+ <string name="physical_keyboard_title" msgid="4811935435315835220">"Vélbúnaðarlyklaborð"</string>
+ <string name="keyboard_layout_dialog_title" msgid="3927180147005616290">"Veldu lyklaskipan"</string>
+ <string name="keyboard_layout_default_label" msgid="1997292217218546957">"Sjálfgefið"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-it/strings.xml b/packages/SettingsLib/res/values-it/strings.xml
index 1552006..703a0b3 100644
--- a/packages/SettingsLib/res/values-it/strings.xml
+++ b/packages/SettingsLib/res/values-it/strings.xml
@@ -528,11 +528,13 @@
<string name="ims_reg_status_not_registered" msgid="2989287366045704694">"Non registrato"</string>
<string name="status_unavailable" msgid="5279036186589861608">"Non disponibile"</string>
<string name="wifi_status_mac_randomized" msgid="466382542497832189">"Selezione casuale dell\'indirizzo MAC"</string>
- <string name="wifi_tether_connected_summary" msgid="5282919920463340158">"{count,plural, =0{0 dispositivi connessi}=1{1 dispositivo connesso}one{# dispositivo connesso}other{# dispositivi connessi}}"</string>
+ <string name="wifi_tether_connected_summary" msgid="5282919920463340158">"{count,plural, =0{0 dispositivi connessi}=1{1 dispositivo connesso}other{# dispositivi connessi}}"</string>
<string name="accessibility_manual_zen_more_time" msgid="5141801092071134235">"Più tempo."</string>
<string name="accessibility_manual_zen_less_time" msgid="6828877595848229965">"Meno tempo."</string>
<string name="cancel" msgid="5665114069455378395">"Annulla"</string>
<string name="okay" msgid="949938843324579502">"OK"</string>
+ <!-- no translation found for done (381184316122520313) -->
+ <skip />
<string name="alarms_and_reminders_label" msgid="6918395649731424294">"Sveglie e promemoria"</string>
<string name="alarms_and_reminders_switch_title" msgid="4939393911531826222">"Consenti l\'impostazione di sveglie e promemoria"</string>
<string name="alarms_and_reminders_title" msgid="8819933264635406032">"Sveglie e promemoria"</string>
@@ -551,7 +553,9 @@
<string name="zen_mode_duration_always_prompt_title" msgid="3212996860498119555">"Chiedi ogni volta"</string>
<string name="zen_mode_forever" msgid="3339224497605461291">"Fino alla disattivazione"</string>
<string name="time_unit_just_now" msgid="3006134267292728099">"Adesso"</string>
- <string name="media_transfer_this_device_name" msgid="2357329267148436433">"Questo telefono"</string>
+ <string name="media_transfer_this_device_name" product="default" msgid="2357329267148436433">"Questo telefono"</string>
+ <!-- no translation found for media_transfer_this_device_name (3714653244000242800) -->
+ <skip />
<string name="media_transfer_this_phone" msgid="7194341457812151531">"Questo telefono"</string>
<string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"Problema di connessione. Spegni e riaccendi il dispositivo"</string>
<string name="media_transfer_wired_device_name" msgid="4447880899964056007">"Dispositivo audio cablato"</string>
@@ -591,7 +595,9 @@
<string name="user_set_lock_button" msgid="1427128184982594856">"Imposta blocco"</string>
<string name="user_switch_to_user" msgid="6975428297154968543">"Passa a <xliff:g id="USER_NAME">%s</xliff:g>"</string>
<string name="creating_new_user_dialog_message" msgid="7232880257538970375">"Creazione nuovo utente…"</string>
+ <string name="creating_new_guest_dialog_message" msgid="1114905602181350690">"Creazione di un nuovo ospite in corso…"</string>
<string name="add_user_failed" msgid="4809887794313944872">"Creazione nuovo utente non riuscita"</string>
+ <string name="add_guest_failed" msgid="8074548434469843443">"Impossibile creare un nuovo ospite"</string>
<string name="user_nickname" msgid="262624187455825083">"Nickname"</string>
<string name="guest_new_guest" msgid="3482026122932643557">"Aggiungi ospite"</string>
<string name="guest_exit_guest" msgid="5908239569510734136">"Rimuovi ospite"</string>
@@ -644,4 +650,7 @@
<string name="dream_complication_title_cast_info" msgid="4038776652841885084">"Info sul cast"</string>
<string name="avatar_picker_title" msgid="8492884172713170652">"Scegli un\'immagine del profilo"</string>
<string name="default_user_icon_description" msgid="6554047177298972638">"Icona dell\'utente predefinito"</string>
+ <string name="physical_keyboard_title" msgid="4811935435315835220">"Tastiera fisica"</string>
+ <string name="keyboard_layout_dialog_title" msgid="3927180147005616290">"Scegli layout tastiera"</string>
+ <string name="keyboard_layout_default_label" msgid="1997292217218546957">"Predefinito"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-iw/strings.xml b/packages/SettingsLib/res/values-iw/strings.xml
index 22810e9..987af9c 100644
--- a/packages/SettingsLib/res/values-iw/strings.xml
+++ b/packages/SettingsLib/res/values-iw/strings.xml
@@ -533,6 +533,8 @@
<string name="accessibility_manual_zen_less_time" msgid="6828877595848229965">"פחות זמן."</string>
<string name="cancel" msgid="5665114069455378395">"ביטול"</string>
<string name="okay" msgid="949938843324579502">"אישור"</string>
+ <!-- no translation found for done (381184316122520313) -->
+ <skip />
<string name="alarms_and_reminders_label" msgid="6918395649731424294">"שעונים מעוררים ותזכורות"</string>
<string name="alarms_and_reminders_switch_title" msgid="4939393911531826222">"אישור להגדיר שעונים מעוררים ותזכורות"</string>
<string name="alarms_and_reminders_title" msgid="8819933264635406032">"שעונים מעוררים ותזכורות"</string>
@@ -551,7 +553,9 @@
<string name="zen_mode_duration_always_prompt_title" msgid="3212996860498119555">"יש לשאול בכל פעם"</string>
<string name="zen_mode_forever" msgid="3339224497605461291">"עד הכיבוי"</string>
<string name="time_unit_just_now" msgid="3006134267292728099">"הרגע"</string>
- <string name="media_transfer_this_device_name" msgid="2357329267148436433">"הטלפון הזה"</string>
+ <string name="media_transfer_this_device_name" product="default" msgid="2357329267148436433">"הטלפון הזה"</string>
+ <!-- no translation found for media_transfer_this_device_name (3714653244000242800) -->
+ <skip />
<string name="media_transfer_this_phone" msgid="7194341457812151531">"הטלפון הזה"</string>
<string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"יש בעיה בחיבור. עליך לכבות את המכשיר ולהפעיל אותו מחדש"</string>
<string name="media_transfer_wired_device_name" msgid="4447880899964056007">"התקן אודיו חוטי"</string>
@@ -591,7 +595,9 @@
<string name="user_set_lock_button" msgid="1427128184982594856">"הגדרת נעילה"</string>
<string name="user_switch_to_user" msgid="6975428297154968543">"מעבר אל <xliff:g id="USER_NAME">%s</xliff:g>"</string>
<string name="creating_new_user_dialog_message" msgid="7232880257538970375">"בתהליך יצירה של משתמש חדש…"</string>
+ <string name="creating_new_guest_dialog_message" msgid="1114905602181350690">"מיד ייווצר אורח חדש…"</string>
<string name="add_user_failed" msgid="4809887794313944872">"לא ניתן היה ליצור משתמש חדש"</string>
+ <string name="add_guest_failed" msgid="8074548434469843443">"יצירת אורח חדש נכשלה"</string>
<string name="user_nickname" msgid="262624187455825083">"כינוי"</string>
<string name="guest_new_guest" msgid="3482026122932643557">"הוספת אורח"</string>
<string name="guest_exit_guest" msgid="5908239569510734136">"הסרת אורח/ת"</string>
@@ -644,4 +650,7 @@
<string name="dream_complication_title_cast_info" msgid="4038776652841885084">"פרטי ההעברה"</string>
<string name="avatar_picker_title" msgid="8492884172713170652">"בחירה של תמונת פרופיל"</string>
<string name="default_user_icon_description" msgid="6554047177298972638">"סמל המשתמש שמוגדר כברירת מחדל"</string>
+ <string name="physical_keyboard_title" msgid="4811935435315835220">"מקלדת פיזית"</string>
+ <string name="keyboard_layout_dialog_title" msgid="3927180147005616290">"בחירה של פריסת המקלדת"</string>
+ <string name="keyboard_layout_default_label" msgid="1997292217218546957">"ברירת מחדל"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-ja/strings.xml b/packages/SettingsLib/res/values-ja/strings.xml
index be98ee4..07b04a8 100644
--- a/packages/SettingsLib/res/values-ja/strings.xml
+++ b/packages/SettingsLib/res/values-ja/strings.xml
@@ -533,6 +533,8 @@
<string name="accessibility_manual_zen_less_time" msgid="6828877595848229965">"短くします。"</string>
<string name="cancel" msgid="5665114069455378395">"キャンセル"</string>
<string name="okay" msgid="949938843324579502">"OK"</string>
+ <!-- no translation found for done (381184316122520313) -->
+ <skip />
<string name="alarms_and_reminders_label" msgid="6918395649731424294">"アラームとリマインダー"</string>
<string name="alarms_and_reminders_switch_title" msgid="4939393911531826222">"アラームとリマインダーの設定を許可する"</string>
<string name="alarms_and_reminders_title" msgid="8819933264635406032">"アラームとリマインダー"</string>
@@ -551,7 +553,9 @@
<string name="zen_mode_duration_always_prompt_title" msgid="3212996860498119555">"毎回確認"</string>
<string name="zen_mode_forever" msgid="3339224497605461291">"OFF にするまで"</string>
<string name="time_unit_just_now" msgid="3006134267292728099">"たった今"</string>
- <string name="media_transfer_this_device_name" msgid="2357329267148436433">"このスマートフォン"</string>
+ <string name="media_transfer_this_device_name" product="default" msgid="2357329267148436433">"このスマートフォン"</string>
+ <!-- no translation found for media_transfer_this_device_name (3714653244000242800) -->
+ <skip />
<string name="media_transfer_this_phone" msgid="7194341457812151531">"このスマートフォン"</string>
<string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"接続エラーです。デバイスを OFF にしてから ON に戻してください"</string>
<string name="media_transfer_wired_device_name" msgid="4447880899964056007">"有線オーディオ デバイス"</string>
@@ -591,7 +595,9 @@
<string name="user_set_lock_button" msgid="1427128184982594856">"ロックを設定"</string>
<string name="user_switch_to_user" msgid="6975428297154968543">"<xliff:g id="USER_NAME">%s</xliff:g> に切り替え"</string>
<string name="creating_new_user_dialog_message" msgid="7232880257538970375">"新しいユーザーを作成しています…"</string>
+ <string name="creating_new_guest_dialog_message" msgid="1114905602181350690">"新しいゲストを作成中…"</string>
<string name="add_user_failed" msgid="4809887794313944872">"新しいユーザーを作成できませんでした"</string>
+ <string name="add_guest_failed" msgid="8074548434469843443">"新しいゲストを作成できませんでした"</string>
<string name="user_nickname" msgid="262624187455825083">"ニックネーム"</string>
<string name="guest_new_guest" msgid="3482026122932643557">"ゲストを追加"</string>
<string name="guest_exit_guest" msgid="5908239569510734136">"ゲストを削除"</string>
@@ -644,4 +650,7 @@
<string name="dream_complication_title_cast_info" msgid="4038776652841885084">"キャスト情報"</string>
<string name="avatar_picker_title" msgid="8492884172713170652">"プロフィール写真の選択"</string>
<string name="default_user_icon_description" msgid="6554047177298972638">"デフォルト ユーザー アイコン"</string>
+ <string name="physical_keyboard_title" msgid="4811935435315835220">"物理キーボード"</string>
+ <string name="keyboard_layout_dialog_title" msgid="3927180147005616290">"キーボード レイアウトの選択"</string>
+ <string name="keyboard_layout_default_label" msgid="1997292217218546957">"デフォルト"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-ka/strings.xml b/packages/SettingsLib/res/values-ka/strings.xml
index f0006d3..a396600 100644
--- a/packages/SettingsLib/res/values-ka/strings.xml
+++ b/packages/SettingsLib/res/values-ka/strings.xml
@@ -533,6 +533,8 @@
<string name="accessibility_manual_zen_less_time" msgid="6828877595848229965">"ნაკლები დრო."</string>
<string name="cancel" msgid="5665114069455378395">"გაუქმება"</string>
<string name="okay" msgid="949938843324579502">"კარგი"</string>
+ <!-- no translation found for done (381184316122520313) -->
+ <skip />
<string name="alarms_and_reminders_label" msgid="6918395649731424294">"მაღვიძარები და შეხსენებები"</string>
<string name="alarms_and_reminders_switch_title" msgid="4939393911531826222">"დაუშვით მაღვიძარების და შეხსენებების დაყენება"</string>
<string name="alarms_and_reminders_title" msgid="8819933264635406032">"მაღვიძარები და შეხსენებები"</string>
@@ -551,7 +553,9 @@
<string name="zen_mode_duration_always_prompt_title" msgid="3212996860498119555">"ყოველთვის მკითხეთ"</string>
<string name="zen_mode_forever" msgid="3339224497605461291">"გამორთვამდე"</string>
<string name="time_unit_just_now" msgid="3006134267292728099">"ახლახან"</string>
- <string name="media_transfer_this_device_name" msgid="2357329267148436433">"ეს ტელეფონი"</string>
+ <string name="media_transfer_this_device_name" product="default" msgid="2357329267148436433">"ეს ტელეფონი"</string>
+ <!-- no translation found for media_transfer_this_device_name (3714653244000242800) -->
+ <skip />
<string name="media_transfer_this_phone" msgid="7194341457812151531">"ეს ტელეფონი"</string>
<string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"დაკავშირებისას წარმოიქმნა პრობლემა. გამორთეთ და კვლავ ჩართეთ მოწყობილობა"</string>
<string name="media_transfer_wired_device_name" msgid="4447880899964056007">"სადენიანი აუდიო მოწყობილობა"</string>
@@ -591,7 +595,9 @@
<string name="user_set_lock_button" msgid="1427128184982594856">"საკეტის დაყენება"</string>
<string name="user_switch_to_user" msgid="6975428297154968543">"<xliff:g id="USER_NAME">%s</xliff:g>-ზე გადართვა"</string>
<string name="creating_new_user_dialog_message" msgid="7232880257538970375">"მიმდინარეობს ახალი მომხმარებლის შექმნა…"</string>
+ <string name="creating_new_guest_dialog_message" msgid="1114905602181350690">"ახალი სტუმრის შექმნა…"</string>
<string name="add_user_failed" msgid="4809887794313944872">"ახალი მომხმარებლის შექმნა ვერ მოხერხდა"</string>
+ <string name="add_guest_failed" msgid="8074548434469843443">"ახალი სტუმრის შექმნა ვერ მოხერხდა"</string>
<string name="user_nickname" msgid="262624187455825083">"მეტსახელი"</string>
<string name="guest_new_guest" msgid="3482026122932643557">"სტუმრის დამატება"</string>
<string name="guest_exit_guest" msgid="5908239569510734136">"სტუმრის ამოშლა"</string>
@@ -644,4 +650,7 @@
<string name="dream_complication_title_cast_info" msgid="4038776652841885084">"ტრანსლირების ინფო"</string>
<string name="avatar_picker_title" msgid="8492884172713170652">"აირჩიეთ პროფილის სურათი"</string>
<string name="default_user_icon_description" msgid="6554047177298972638">"მომხმარებლის ნაგულისხმევი ხატულა"</string>
+ <string name="physical_keyboard_title" msgid="4811935435315835220">"ფიზიკური კლავიატურა"</string>
+ <string name="keyboard_layout_dialog_title" msgid="3927180147005616290">"აირჩიე კლავიატურის განლაგება"</string>
+ <string name="keyboard_layout_default_label" msgid="1997292217218546957">"ნაგულისხმევი"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-kk/strings.xml b/packages/SettingsLib/res/values-kk/strings.xml
index 3724ca5..ccaf1c4 100644
--- a/packages/SettingsLib/res/values-kk/strings.xml
+++ b/packages/SettingsLib/res/values-kk/strings.xml
@@ -533,6 +533,8 @@
<string name="accessibility_manual_zen_less_time" msgid="6828877595848229965">"Азырақ уақыт."</string>
<string name="cancel" msgid="5665114069455378395">"Бас тарту"</string>
<string name="okay" msgid="949938843324579502">"Жарайды"</string>
+ <!-- no translation found for done (381184316122520313) -->
+ <skip />
<string name="alarms_and_reminders_label" msgid="6918395649731424294">"Оятқыш және еске салғыш"</string>
<string name="alarms_and_reminders_switch_title" msgid="4939393911531826222">"Оятқыштар мен еске салғыштарды орнатуға рұқсат беру"</string>
<string name="alarms_and_reminders_title" msgid="8819933264635406032">"Оятқыштар мен еске салғыштар"</string>
@@ -551,7 +553,9 @@
<string name="zen_mode_duration_always_prompt_title" msgid="3212996860498119555">"Әрдайым сұрау"</string>
<string name="zen_mode_forever" msgid="3339224497605461291">"Өшірілгенге дейін"</string>
<string name="time_unit_just_now" msgid="3006134267292728099">"Дәл қазір"</string>
- <string name="media_transfer_this_device_name" msgid="2357329267148436433">"Осы телефон"</string>
+ <string name="media_transfer_this_device_name" product="default" msgid="2357329267148436433">"Осы телефон"</string>
+ <!-- no translation found for media_transfer_this_device_name (3714653244000242800) -->
+ <skip />
<string name="media_transfer_this_phone" msgid="7194341457812151531">"Осы телефон"</string>
<string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"Байланыс орнату қатесі шығуып жатыр. Құрылғыны өшіріп, қайта қосыңыз."</string>
<string name="media_transfer_wired_device_name" msgid="4447880899964056007">"Сымды аудио құрылғысы"</string>
@@ -591,7 +595,9 @@
<string name="user_set_lock_button" msgid="1427128184982594856">"Бекітпе тағайындау"</string>
<string name="user_switch_to_user" msgid="6975428297154968543">"<xliff:g id="USER_NAME">%s</xliff:g> пайдаланушысына ауысу"</string>
<string name="creating_new_user_dialog_message" msgid="7232880257538970375">"Жаңа пайдаланушы профилі жасалуда…"</string>
+ <string name="creating_new_guest_dialog_message" msgid="1114905602181350690">"Жаңа қонақ профилі жасалуда…"</string>
<string name="add_user_failed" msgid="4809887794313944872">"Жаңа пайдаланушы жасалмады."</string>
+ <string name="add_guest_failed" msgid="8074548434469843443">"Жаңа қонақ профилі жасалмады."</string>
<string name="user_nickname" msgid="262624187455825083">"Лақап ат"</string>
<string name="guest_new_guest" msgid="3482026122932643557">"Қонақ қосу"</string>
<string name="guest_exit_guest" msgid="5908239569510734136">"Қонақты жою"</string>
@@ -644,4 +650,7 @@
<string name="dream_complication_title_cast_info" msgid="4038776652841885084">"Трансляция ақпараты"</string>
<string name="avatar_picker_title" msgid="8492884172713170652">"Профиль суретін таңдау"</string>
<string name="default_user_icon_description" msgid="6554047177298972638">"Әдепкі пайдаланушы белгішесі"</string>
+ <string name="physical_keyboard_title" msgid="4811935435315835220">"Пернетақта"</string>
+ <string name="keyboard_layout_dialog_title" msgid="3927180147005616290">"Пернетақтаның орналасу ретін таңдау"</string>
+ <string name="keyboard_layout_default_label" msgid="1997292217218546957">"Әдепкі"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-km/strings.xml b/packages/SettingsLib/res/values-km/strings.xml
index 28211f0..370fc4b 100644
--- a/packages/SettingsLib/res/values-km/strings.xml
+++ b/packages/SettingsLib/res/values-km/strings.xml
@@ -533,6 +533,8 @@
<string name="accessibility_manual_zen_less_time" msgid="6828877595848229965">"រយៈពេលតិចជាង។"</string>
<string name="cancel" msgid="5665114069455378395">"បោះបង់"</string>
<string name="okay" msgid="949938843324579502">"យល់ព្រម"</string>
+ <!-- no translation found for done (381184316122520313) -->
+ <skip />
<string name="alarms_and_reminders_label" msgid="6918395649731424294">"ម៉ោងរោទ៍ និងការរំលឹក"</string>
<string name="alarms_and_reminders_switch_title" msgid="4939393911531826222">"អនុញ្ញាតឱ្យកំណត់ម៉ោងរោទ៍ និងការរំលឹក"</string>
<string name="alarms_and_reminders_title" msgid="8819933264635406032">"ម៉ោងរោទ៍ និងការរំលឹក"</string>
@@ -551,7 +553,9 @@
<string name="zen_mode_duration_always_prompt_title" msgid="3212996860498119555">"សួរគ្រប់ពេល"</string>
<string name="zen_mode_forever" msgid="3339224497605461291">"រហូតទាល់តែអ្នកបិទ"</string>
<string name="time_unit_just_now" msgid="3006134267292728099">"អម្បាញ់មិញ"</string>
- <string name="media_transfer_this_device_name" msgid="2357329267148436433">"ទូរសព្ទនេះ"</string>
+ <string name="media_transfer_this_device_name" product="default" msgid="2357329267148436433">"ទូរសព្ទនេះ"</string>
+ <!-- no translation found for media_transfer_this_device_name (3714653244000242800) -->
+ <skip />
<string name="media_transfer_this_phone" msgid="7194341457812151531">"ទូរសព្ទនេះ"</string>
<string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"មានបញ្ហាក្នុងការភ្ជាប់។ បិទ រួចបើកឧបករណ៍វិញ"</string>
<string name="media_transfer_wired_device_name" msgid="4447880899964056007">"ឧបករណ៍សំឡេងប្រើខ្សែ"</string>
@@ -591,7 +595,9 @@
<string name="user_set_lock_button" msgid="1427128184982594856">"កំណត់ការចាក់សោ"</string>
<string name="user_switch_to_user" msgid="6975428297154968543">"ប្ដូរទៅ <xliff:g id="USER_NAME">%s</xliff:g>"</string>
<string name="creating_new_user_dialog_message" msgid="7232880257538970375">"កំពុងបង្កើតអ្នកប្រើប្រាស់ថ្មី…"</string>
+ <string name="creating_new_guest_dialog_message" msgid="1114905602181350690">"កំពុងបង្កើតភ្ញៀវថ្មី…"</string>
<string name="add_user_failed" msgid="4809887794313944872">"មិនអាចបង្កើតអ្នកប្រើប្រាស់ថ្មីបានទេ"</string>
+ <string name="add_guest_failed" msgid="8074548434469843443">"មិនអាចបង្កើតភ្ញៀវថ្មីបានទេ"</string>
<string name="user_nickname" msgid="262624187455825083">"ឈ្មោះហៅក្រៅ"</string>
<string name="guest_new_guest" msgid="3482026122932643557">"បញ្ចូលភ្ញៀវ"</string>
<string name="guest_exit_guest" msgid="5908239569510734136">"ដកភ្ញៀវចេញ"</string>
@@ -644,4 +650,10 @@
<string name="dream_complication_title_cast_info" msgid="4038776652841885084">"ព័ត៌មានអំពីការបញ្ជូន"</string>
<string name="avatar_picker_title" msgid="8492884172713170652">"ជ្រើសរើសរូបភាពកម្រងព័ត៌មាន"</string>
<string name="default_user_icon_description" msgid="6554047177298972638">"រូបអ្នកប្រើប្រាស់លំនាំដើម"</string>
+ <!-- no translation found for physical_keyboard_title (4811935435315835220) -->
+ <skip />
+ <!-- no translation found for keyboard_layout_dialog_title (3927180147005616290) -->
+ <skip />
+ <!-- no translation found for keyboard_layout_default_label (1997292217218546957) -->
+ <skip />
</resources>
diff --git a/packages/SettingsLib/res/values-kn/strings.xml b/packages/SettingsLib/res/values-kn/strings.xml
index 635c687..a070ad2 100644
--- a/packages/SettingsLib/res/values-kn/strings.xml
+++ b/packages/SettingsLib/res/values-kn/strings.xml
@@ -533,6 +533,8 @@
<string name="accessibility_manual_zen_less_time" msgid="6828877595848229965">"ಕಡಿಮೆ ಸಮಯ."</string>
<string name="cancel" msgid="5665114069455378395">"ರದ್ದುಮಾಡಿ"</string>
<string name="okay" msgid="949938843324579502">"ಸರಿ"</string>
+ <!-- no translation found for done (381184316122520313) -->
+ <skip />
<string name="alarms_and_reminders_label" msgid="6918395649731424294">"ಅಲಾರಾಮ್ಗಳು ಮತ್ತು ರಿಮೈಂಡರ್ಗಳು"</string>
<string name="alarms_and_reminders_switch_title" msgid="4939393911531826222">"ಅಲಾರಂಗಳು ಮತ್ತು ರಿಮೈಂಡರ್ಗಳನ್ನು ಹೊಂದಿಸಲು ಅನುಮತಿಸಿ"</string>
<string name="alarms_and_reminders_title" msgid="8819933264635406032">"ಅಲಾರಂಗಳು ಮತ್ತು ರಿಮೈಂಡರ್ಗಳು"</string>
@@ -551,7 +553,9 @@
<string name="zen_mode_duration_always_prompt_title" msgid="3212996860498119555">"ಪ್ರತಿ ಬಾರಿ ಕೇಳಿ"</string>
<string name="zen_mode_forever" msgid="3339224497605461291">"ನೀವು ಆಫ್ ಮಾಡುವವರೆಗೆ"</string>
<string name="time_unit_just_now" msgid="3006134267292728099">"ಇದೀಗ"</string>
- <string name="media_transfer_this_device_name" msgid="2357329267148436433">"ಈ ಫೋನ್"</string>
+ <string name="media_transfer_this_device_name" product="default" msgid="2357329267148436433">"ಈ ಫೋನ್"</string>
+ <!-- no translation found for media_transfer_this_device_name (3714653244000242800) -->
+ <skip />
<string name="media_transfer_this_phone" msgid="7194341457812151531">"ಈ ಫೋನ್"</string>
<string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"ಕನೆಕ್ಟ್ ಮಾಡುವಾಗ ಸಮಸ್ಯೆ ಎದುರಾಗಿದೆ ಸಾಧನವನ್ನು ಆಫ್ ಮಾಡಿ ಹಾಗೂ ನಂತರ ಪುನಃ ಆನ್ ಮಾಡಿ"</string>
<string name="media_transfer_wired_device_name" msgid="4447880899964056007">"ವೈರ್ ಹೊಂದಿರುವ ಆಡಿಯೋ ಸಾಧನ"</string>
@@ -591,7 +595,9 @@
<string name="user_set_lock_button" msgid="1427128184982594856">"ಲಾಕ್ ಹೊಂದಿಸಿ"</string>
<string name="user_switch_to_user" msgid="6975428297154968543">"<xliff:g id="USER_NAME">%s</xliff:g> ಗೆ ಬದಲಿಸಿ"</string>
<string name="creating_new_user_dialog_message" msgid="7232880257538970375">"ಹೊಸ ಬಳಕೆದಾರರನ್ನು ರಚಿಸಲಾಗುತ್ತಿದೆ…"</string>
+ <string name="creating_new_guest_dialog_message" msgid="1114905602181350690">"ಹೊಸ ಅತಿಥಿಯನ್ನು ರಚಿಸಲಾಗುತ್ತಿದೆ…"</string>
<string name="add_user_failed" msgid="4809887794313944872">"ಹೊಸ ಬಳಕೆದಾರರನ್ನು ರಚಿಸಲು ವಿಫಲವಾಗಿದೆ"</string>
+ <string name="add_guest_failed" msgid="8074548434469843443">"ಹೊಸ ಅತಿಥಿಯನ್ನು ರಚಿಸಲು ವಿಫಲವಾಗಿದೆ"</string>
<string name="user_nickname" msgid="262624187455825083">"ಅಡ್ಡ ಹೆಸರು"</string>
<string name="guest_new_guest" msgid="3482026122932643557">"ಅತಿಥಿಯನ್ನು ಸೇರಿಸಿ"</string>
<string name="guest_exit_guest" msgid="5908239569510734136">"ಅತಿಥಿಯನ್ನು ತೆಗೆದುಹಾಕಿ"</string>
@@ -644,4 +650,7 @@
<string name="dream_complication_title_cast_info" msgid="4038776652841885084">"ಬಿತ್ತರಿಸಿದ ಮಾಹಿತಿ"</string>
<string name="avatar_picker_title" msgid="8492884172713170652">"ಪ್ರೊಫೈಲ್ ಚಿತ್ರವನ್ನು ಆಯ್ಕೆ ಮಾಡಿ"</string>
<string name="default_user_icon_description" msgid="6554047177298972638">"ಡೀಫಾಲ್ಟ್ ಬಳಕೆದಾರರ ಐಕಾನ್"</string>
+ <string name="physical_keyboard_title" msgid="4811935435315835220">"ಭೌತಿಕ ಕೀಬೋರ್ಡ್"</string>
+ <string name="keyboard_layout_dialog_title" msgid="3927180147005616290">"ಕೀಬೋರ್ಡ್ ಲೇಔಟ್ ಆರಿಸಿ"</string>
+ <string name="keyboard_layout_default_label" msgid="1997292217218546957">"ಡೀಫಾಲ್ಟ್"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-ko/strings.xml b/packages/SettingsLib/res/values-ko/strings.xml
index 40acb1a..3cd8583 100644
--- a/packages/SettingsLib/res/values-ko/strings.xml
+++ b/packages/SettingsLib/res/values-ko/strings.xml
@@ -533,6 +533,8 @@
<string name="accessibility_manual_zen_less_time" msgid="6828877595848229965">"시간 줄이기"</string>
<string name="cancel" msgid="5665114069455378395">"취소"</string>
<string name="okay" msgid="949938843324579502">"확인"</string>
+ <!-- no translation found for done (381184316122520313) -->
+ <skip />
<string name="alarms_and_reminders_label" msgid="6918395649731424294">"알람 및 리마인더"</string>
<string name="alarms_and_reminders_switch_title" msgid="4939393911531826222">"알람 및 리마인더 설정 허용"</string>
<string name="alarms_and_reminders_title" msgid="8819933264635406032">"알람 및 리마인더"</string>
@@ -551,7 +553,9 @@
<string name="zen_mode_duration_always_prompt_title" msgid="3212996860498119555">"항상 확인"</string>
<string name="zen_mode_forever" msgid="3339224497605461291">"사용 중지할 때까지"</string>
<string name="time_unit_just_now" msgid="3006134267292728099">"조금 전"</string>
- <string name="media_transfer_this_device_name" msgid="2357329267148436433">"이 휴대전화"</string>
+ <string name="media_transfer_this_device_name" product="default" msgid="2357329267148436433">"이 휴대전화"</string>
+ <!-- no translation found for media_transfer_this_device_name (3714653244000242800) -->
+ <skip />
<string name="media_transfer_this_phone" msgid="7194341457812151531">"이 휴대전화"</string>
<string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"연결 중에 문제가 발생했습니다. 기기를 껐다가 다시 켜 보세요."</string>
<string name="media_transfer_wired_device_name" msgid="4447880899964056007">"유선 오디오 기기"</string>
@@ -591,7 +595,9 @@
<string name="user_set_lock_button" msgid="1427128184982594856">"잠금 설정"</string>
<string name="user_switch_to_user" msgid="6975428297154968543">"<xliff:g id="USER_NAME">%s</xliff:g>(으)로 전환"</string>
<string name="creating_new_user_dialog_message" msgid="7232880257538970375">"새로운 사용자를 만드는 중…"</string>
+ <string name="creating_new_guest_dialog_message" msgid="1114905602181350690">"새 게스트 생성 중…"</string>
<string name="add_user_failed" msgid="4809887794313944872">"새 사용자를 만들지 못함"</string>
+ <string name="add_guest_failed" msgid="8074548434469843443">"새 게스트 생성 실패"</string>
<string name="user_nickname" msgid="262624187455825083">"닉네임"</string>
<string name="guest_new_guest" msgid="3482026122932643557">"게스트 추가"</string>
<string name="guest_exit_guest" msgid="5908239569510734136">"게스트 삭제"</string>
@@ -644,4 +650,7 @@
<string name="dream_complication_title_cast_info" msgid="4038776652841885084">"전송 정보"</string>
<string name="avatar_picker_title" msgid="8492884172713170652">"프로필 사진 선택하기"</string>
<string name="default_user_icon_description" msgid="6554047177298972638">"기본 사용자 아이콘"</string>
+ <string name="physical_keyboard_title" msgid="4811935435315835220">"물리적 키보드"</string>
+ <string name="keyboard_layout_dialog_title" msgid="3927180147005616290">"키보드 레이아웃 선택"</string>
+ <string name="keyboard_layout_default_label" msgid="1997292217218546957">"기본"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-ky/strings.xml b/packages/SettingsLib/res/values-ky/strings.xml
index 7a50ece..93c4321 100644
--- a/packages/SettingsLib/res/values-ky/strings.xml
+++ b/packages/SettingsLib/res/values-ky/strings.xml
@@ -533,6 +533,8 @@
<string name="accessibility_manual_zen_less_time" msgid="6828877595848229965">"Азыраак убакыт."</string>
<string name="cancel" msgid="5665114069455378395">"Жок"</string>
<string name="okay" msgid="949938843324579502">"OK"</string>
+ <!-- no translation found for done (381184316122520313) -->
+ <skip />
<string name="alarms_and_reminders_label" msgid="6918395649731424294">"Ойготкучтар жана эстеткичтер"</string>
<string name="alarms_and_reminders_switch_title" msgid="4939393911531826222">"Ойготкуч жана эстеткичтерди коюуга уруксат берүү"</string>
<string name="alarms_and_reminders_title" msgid="8819933264635406032">"Ойготкучтар жана эстеткичтер"</string>
@@ -551,7 +553,9 @@
<string name="zen_mode_duration_always_prompt_title" msgid="3212996860498119555">"Ар дайым суралсын"</string>
<string name="zen_mode_forever" msgid="3339224497605461291">"Бул функция өчүрүлгөнгө чейин"</string>
<string name="time_unit_just_now" msgid="3006134267292728099">"Жаңы эле"</string>
- <string name="media_transfer_this_device_name" msgid="2357329267148436433">"Ушул телефон"</string>
+ <string name="media_transfer_this_device_name" product="default" msgid="2357329267148436433">"Ушул телефон"</string>
+ <!-- no translation found for media_transfer_this_device_name (3714653244000242800) -->
+ <skip />
<string name="media_transfer_this_phone" msgid="7194341457812151531">"Ушул телефон"</string>
<string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"Туташууда маселе келип чыкты. Түзмөктү өчүрүп, кайра күйгүзүп көрүңүз"</string>
<string name="media_transfer_wired_device_name" msgid="4447880899964056007">"Зымдуу аудио түзмөк"</string>
@@ -591,7 +595,9 @@
<string name="user_set_lock_button" msgid="1427128184982594856">"Бөгөт коюу"</string>
<string name="user_switch_to_user" msgid="6975428297154968543">"<xliff:g id="USER_NAME">%s</xliff:g> аккаунтуна которулуу"</string>
<string name="creating_new_user_dialog_message" msgid="7232880257538970375">"Жаңы колдонуучу түзүлүүдө…"</string>
+ <string name="creating_new_guest_dialog_message" msgid="1114905602181350690">"Жаңы конок түзүлүүдө…"</string>
<string name="add_user_failed" msgid="4809887794313944872">"Жаңы колдонуучу түзүлбөй калды"</string>
+ <string name="add_guest_failed" msgid="8074548434469843443">"Жаңы конок түзүлгөн жок"</string>
<string name="user_nickname" msgid="262624187455825083">"Ылакап аты"</string>
<string name="guest_new_guest" msgid="3482026122932643557">"Конок кошуу"</string>
<string name="guest_exit_guest" msgid="5908239569510734136">"Конокту өчүрүү"</string>
@@ -644,4 +650,7 @@
<string name="dream_complication_title_cast_info" msgid="4038776652841885084">"Тышкы экранга чыгаруу маалыматы"</string>
<string name="avatar_picker_title" msgid="8492884172713170652">"Профилдин сүрөтүн тандоо"</string>
<string name="default_user_icon_description" msgid="6554047177298972638">"Демейки колдонуучунун сүрөтчөсү"</string>
+ <string name="physical_keyboard_title" msgid="4811935435315835220">"Аппараттык баскычтоп"</string>
+ <string name="keyboard_layout_dialog_title" msgid="3927180147005616290">"Тергичтин жайылмасын тандоо"</string>
+ <string name="keyboard_layout_default_label" msgid="1997292217218546957">"Демейки"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-lo/strings.xml b/packages/SettingsLib/res/values-lo/strings.xml
index 2aced9d..e4d677d 100644
--- a/packages/SettingsLib/res/values-lo/strings.xml
+++ b/packages/SettingsLib/res/values-lo/strings.xml
@@ -533,6 +533,8 @@
<string name="accessibility_manual_zen_less_time" msgid="6828877595848229965">"ຫຼຸດເວລາ."</string>
<string name="cancel" msgid="5665114069455378395">"ຍົກເລີກ"</string>
<string name="okay" msgid="949938843324579502">"ຕົກລົງ"</string>
+ <!-- no translation found for done (381184316122520313) -->
+ <skip />
<string name="alarms_and_reminders_label" msgid="6918395649731424294">"ໂມງປຸກ ແລະ ການແຈ້ງເຕືອນ"</string>
<string name="alarms_and_reminders_switch_title" msgid="4939393911531826222">"ອະນຸຍາດໃຫ້ຕັ້ງໂມງປຸກ ແລະ ການແຈ້ງເຕືອນ"</string>
<string name="alarms_and_reminders_title" msgid="8819933264635406032">"ໂມງປຸກ ແລະ ການແຈ້ງເຕືອນ"</string>
@@ -551,7 +553,9 @@
<string name="zen_mode_duration_always_prompt_title" msgid="3212996860498119555">"ຖາມທຸກເທື່ອ"</string>
<string name="zen_mode_forever" msgid="3339224497605461291">"ຈົນກວ່າທ່ານຈະປິດ"</string>
<string name="time_unit_just_now" msgid="3006134267292728099">"ຕອນນີ້"</string>
- <string name="media_transfer_this_device_name" msgid="2357329267148436433">"ໂທລະສັບນີ້"</string>
+ <string name="media_transfer_this_device_name" product="default" msgid="2357329267148436433">"ໂທລະສັບນີ້"</string>
+ <!-- no translation found for media_transfer_this_device_name (3714653244000242800) -->
+ <skip />
<string name="media_transfer_this_phone" msgid="7194341457812151531">"ໂທລະສັບນີ້"</string>
<string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"ເກີດບັນຫາໃນການເຊື່ອມຕໍ່. ປິດອຸປະກອນແລ້ວເປີດກັບຄືນມາໃໝ່"</string>
<string name="media_transfer_wired_device_name" msgid="4447880899964056007">"ອຸປະກອນສຽງແບບມີສາຍ"</string>
@@ -591,7 +595,9 @@
<string name="user_set_lock_button" msgid="1427128184982594856">"ຕັ້ງການລັອກ"</string>
<string name="user_switch_to_user" msgid="6975428297154968543">"ສະຫຼັບໄປ <xliff:g id="USER_NAME">%s</xliff:g>"</string>
<string name="creating_new_user_dialog_message" msgid="7232880257538970375">"ກຳລັງສ້າງຜູ້ໃຊ້ໃໝ່…"</string>
+ <string name="creating_new_guest_dialog_message" msgid="1114905602181350690">"ກຳລັງສ້າງແຂກໃໝ່…"</string>
<string name="add_user_failed" msgid="4809887794313944872">"ສ້າງຜູ້ໃຊ້ໃໝ່ບໍ່ສຳເລັດ"</string>
+ <string name="add_guest_failed" msgid="8074548434469843443">"ສ້າງແຂກໃໝ່ບໍ່ສຳເລັດ"</string>
<string name="user_nickname" msgid="262624187455825083">"ຊື່ຫຼິ້ນ"</string>
<string name="guest_new_guest" msgid="3482026122932643557">"ເພີ່ມແຂກ"</string>
<string name="guest_exit_guest" msgid="5908239569510734136">"ລຶບແຂກອອກ"</string>
@@ -644,4 +650,7 @@
<string name="dream_complication_title_cast_info" msgid="4038776652841885084">"ຂໍ້ມູນການສົ່ງສັນຍານ"</string>
<string name="avatar_picker_title" msgid="8492884172713170652">"ເລືອກຮູບໂປຣໄຟລ໌"</string>
<string name="default_user_icon_description" msgid="6554047177298972638">"ໄອຄອນຜູ້ໃຊ້ເລີ່ມຕົ້ນ"</string>
+ <string name="physical_keyboard_title" msgid="4811935435315835220">"ແປ້ນພິມພາຍນອກ"</string>
+ <string name="keyboard_layout_dialog_title" msgid="3927180147005616290">"ເລືອກຮູບແບບແປ້ນພິມ"</string>
+ <string name="keyboard_layout_default_label" msgid="1997292217218546957">"ຄ່າເລີ່ມຕົ້ນ"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-lt/strings.xml b/packages/SettingsLib/res/values-lt/strings.xml
index 6e7daa7..fbd800c 100644
--- a/packages/SettingsLib/res/values-lt/strings.xml
+++ b/packages/SettingsLib/res/values-lt/strings.xml
@@ -533,6 +533,8 @@
<string name="accessibility_manual_zen_less_time" msgid="6828877595848229965">"Mažiau laiko."</string>
<string name="cancel" msgid="5665114069455378395">"Atšaukti"</string>
<string name="okay" msgid="949938843324579502">"Gerai"</string>
+ <!-- no translation found for done (381184316122520313) -->
+ <skip />
<string name="alarms_and_reminders_label" msgid="6918395649731424294">"Signalai ir priminimai"</string>
<string name="alarms_and_reminders_switch_title" msgid="4939393911531826222">"Leisti nustatyti signalus ir priminimus"</string>
<string name="alarms_and_reminders_title" msgid="8819933264635406032">"Signalai ir priminimai"</string>
@@ -551,7 +553,9 @@
<string name="zen_mode_duration_always_prompt_title" msgid="3212996860498119555">"Klausti kaskart"</string>
<string name="zen_mode_forever" msgid="3339224497605461291">"Kol išjungsite"</string>
<string name="time_unit_just_now" msgid="3006134267292728099">"Ką tik"</string>
- <string name="media_transfer_this_device_name" msgid="2357329267148436433">"Šis telefonas"</string>
+ <string name="media_transfer_this_device_name" product="default" msgid="2357329267148436433">"Šis telefonas"</string>
+ <!-- no translation found for media_transfer_this_device_name (3714653244000242800) -->
+ <skip />
<string name="media_transfer_this_phone" msgid="7194341457812151531">"Šis telefonas"</string>
<string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"Prisijungiant kilo problema. Išjunkite įrenginį ir vėl jį įjunkite"</string>
<string name="media_transfer_wired_device_name" msgid="4447880899964056007">"Laidinis garso įrenginys"</string>
@@ -591,7 +595,9 @@
<string name="user_set_lock_button" msgid="1427128184982594856">"Nustatyti užraktą"</string>
<string name="user_switch_to_user" msgid="6975428297154968543">"Perjungti į <xliff:g id="USER_NAME">%s</xliff:g>"</string>
<string name="creating_new_user_dialog_message" msgid="7232880257538970375">"Kuriamas naujas naudotojas…"</string>
+ <string name="creating_new_guest_dialog_message" msgid="1114905602181350690">"Kuriamas naujas gestas…"</string>
<string name="add_user_failed" msgid="4809887794313944872">"Nepavyko sukurti naujo naudotojo"</string>
+ <string name="add_guest_failed" msgid="8074548434469843443">"Nepavyko sukurti naujo gesto"</string>
<string name="user_nickname" msgid="262624187455825083">"Slapyvardis"</string>
<string name="guest_new_guest" msgid="3482026122932643557">"Pridėti svečią"</string>
<string name="guest_exit_guest" msgid="5908239569510734136">"Pašalinti svečią"</string>
@@ -644,4 +650,7 @@
<string name="dream_complication_title_cast_info" msgid="4038776652841885084">"Perdav. informacija"</string>
<string name="avatar_picker_title" msgid="8492884172713170652">"Pasirinkite profilio nuotrauką"</string>
<string name="default_user_icon_description" msgid="6554047177298972638">"Numatytojo naudotojo piktograma"</string>
+ <string name="physical_keyboard_title" msgid="4811935435315835220">"Fizinė klaviatūra"</string>
+ <string name="keyboard_layout_dialog_title" msgid="3927180147005616290">"Klaviatūros išdėstymo pasirinkimas"</string>
+ <string name="keyboard_layout_default_label" msgid="1997292217218546957">"Numatytasis"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-lv/strings.xml b/packages/SettingsLib/res/values-lv/strings.xml
index 0d6651a..5ef979e 100644
--- a/packages/SettingsLib/res/values-lv/strings.xml
+++ b/packages/SettingsLib/res/values-lv/strings.xml
@@ -533,6 +533,8 @@
<string name="accessibility_manual_zen_less_time" msgid="6828877595848229965">"Mazāk laika."</string>
<string name="cancel" msgid="5665114069455378395">"Atcelt"</string>
<string name="okay" msgid="949938843324579502">"LABI"</string>
+ <!-- no translation found for done (381184316122520313) -->
+ <skip />
<string name="alarms_and_reminders_label" msgid="6918395649731424294">"Signāli un atgādinājumi"</string>
<string name="alarms_and_reminders_switch_title" msgid="4939393911531826222">"Atļaut iestatīt signālus un atgādinājumus"</string>
<string name="alarms_and_reminders_title" msgid="8819933264635406032">"Signāli un atgādinājumi"</string>
@@ -551,7 +553,9 @@
<string name="zen_mode_duration_always_prompt_title" msgid="3212996860498119555">"Vaicāt katru reizi"</string>
<string name="zen_mode_forever" msgid="3339224497605461291">"Līdz brīdim, kad izslēgsiet"</string>
<string name="time_unit_just_now" msgid="3006134267292728099">"Tikko"</string>
- <string name="media_transfer_this_device_name" msgid="2357329267148436433">"Šis tālrunis"</string>
+ <string name="media_transfer_this_device_name" product="default" msgid="2357329267148436433">"Šis tālrunis"</string>
+ <!-- no translation found for media_transfer_this_device_name (3714653244000242800) -->
+ <skip />
<string name="media_transfer_this_phone" msgid="7194341457812151531">"Šis tālrunis"</string>
<string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"Radās problēma ar savienojuma izveidi. Izslēdziet un atkal ieslēdziet ierīci."</string>
<string name="media_transfer_wired_device_name" msgid="4447880899964056007">"Vadu audioierīce"</string>
@@ -591,7 +595,9 @@
<string name="user_set_lock_button" msgid="1427128184982594856">"Iestatīt bloķēšanu"</string>
<string name="user_switch_to_user" msgid="6975428297154968543">"Pārslēgties uz: <xliff:g id="USER_NAME">%s</xliff:g>"</string>
<string name="creating_new_user_dialog_message" msgid="7232880257538970375">"Notiek jauna lietotāja izveide…"</string>
+ <string name="creating_new_guest_dialog_message" msgid="1114905602181350690">"Notiek jauna viesa profila izveide…"</string>
<string name="add_user_failed" msgid="4809887794313944872">"Neizdevās izveidot jaunu lietotāju"</string>
+ <string name="add_guest_failed" msgid="8074548434469843443">"Neizdevās izveidot jaunu viesa profilu"</string>
<string name="user_nickname" msgid="262624187455825083">"Segvārds"</string>
<string name="guest_new_guest" msgid="3482026122932643557">"Pievienot viesi"</string>
<string name="guest_exit_guest" msgid="5908239569510734136">"Noņemt viesi"</string>
@@ -644,4 +650,7 @@
<string name="dream_complication_title_cast_info" msgid="4038776652841885084">"Apraides informācija"</string>
<string name="avatar_picker_title" msgid="8492884172713170652">"Profila attēla izvēle"</string>
<string name="default_user_icon_description" msgid="6554047177298972638">"Noklusējuma lietotāja ikona"</string>
+ <string name="physical_keyboard_title" msgid="4811935435315835220">"Fiziskā tastatūra"</string>
+ <string name="keyboard_layout_dialog_title" msgid="3927180147005616290">"Tastatūras izkārtojuma izvēle"</string>
+ <string name="keyboard_layout_default_label" msgid="1997292217218546957">"Noklusējums"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-mk/strings.xml b/packages/SettingsLib/res/values-mk/strings.xml
index 8111ec0..85788103 100644
--- a/packages/SettingsLib/res/values-mk/strings.xml
+++ b/packages/SettingsLib/res/values-mk/strings.xml
@@ -533,6 +533,8 @@
<string name="accessibility_manual_zen_less_time" msgid="6828877595848229965">"Помалку време."</string>
<string name="cancel" msgid="5665114069455378395">"Откажи"</string>
<string name="okay" msgid="949938843324579502">"Во ред"</string>
+ <!-- no translation found for done (381184316122520313) -->
+ <skip />
<string name="alarms_and_reminders_label" msgid="6918395649731424294">"Аларми и потсетници"</string>
<string name="alarms_and_reminders_switch_title" msgid="4939393911531826222">"Дозволи поставување аларми и потсетници"</string>
<string name="alarms_and_reminders_title" msgid="8819933264635406032">"Аларми и потсетници"</string>
@@ -551,7 +553,9 @@
<string name="zen_mode_duration_always_prompt_title" msgid="3212996860498119555">"Прашувај секогаш"</string>
<string name="zen_mode_forever" msgid="3339224497605461291">"Додека не го исклучите"</string>
<string name="time_unit_just_now" msgid="3006134267292728099">"Пред малку"</string>
- <string name="media_transfer_this_device_name" msgid="2357329267148436433">"Овој телефон"</string>
+ <string name="media_transfer_this_device_name" product="default" msgid="2357329267148436433">"Овој телефон"</string>
+ <!-- no translation found for media_transfer_this_device_name (3714653244000242800) -->
+ <skip />
<string name="media_transfer_this_phone" msgid="7194341457812151531">"Овој телефон"</string>
<string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"Проблем со поврзување. Исклучете го уредот и повторно вклучете го"</string>
<string name="media_transfer_wired_device_name" msgid="4447880899964056007">"Жичен аудиоуред"</string>
@@ -591,7 +595,9 @@
<string name="user_set_lock_button" msgid="1427128184982594856">"Постави заклучување"</string>
<string name="user_switch_to_user" msgid="6975428297154968543">"Префрли на <xliff:g id="USER_NAME">%s</xliff:g>"</string>
<string name="creating_new_user_dialog_message" msgid="7232880257538970375">"Се создава нов корисник…"</string>
+ <string name="creating_new_guest_dialog_message" msgid="1114905602181350690">"Се создава нов гостин…"</string>
<string name="add_user_failed" msgid="4809887794313944872">"Не успеа да создаде нов корисник"</string>
+ <string name="add_guest_failed" msgid="8074548434469843443">"Не успеа создавањето нов гостин"</string>
<string name="user_nickname" msgid="262624187455825083">"Прекар"</string>
<string name="guest_new_guest" msgid="3482026122932643557">"Додајте гостин"</string>
<string name="guest_exit_guest" msgid="5908239569510734136">"Отстрани гостин"</string>
@@ -644,4 +650,7 @@
<string name="dream_complication_title_cast_info" msgid="4038776652841885084">"Инфо за улогите"</string>
<string name="avatar_picker_title" msgid="8492884172713170652">"Изберете профилна слика"</string>
<string name="default_user_icon_description" msgid="6554047177298972638">"Икона за стандарден корисник"</string>
+ <string name="physical_keyboard_title" msgid="4811935435315835220">"Физичка тастатура"</string>
+ <string name="keyboard_layout_dialog_title" msgid="3927180147005616290">"Избери распоред на тастатура"</string>
+ <string name="keyboard_layout_default_label" msgid="1997292217218546957">"Стандардно"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-ml/strings.xml b/packages/SettingsLib/res/values-ml/strings.xml
index 0ae164b..5abb782 100644
--- a/packages/SettingsLib/res/values-ml/strings.xml
+++ b/packages/SettingsLib/res/values-ml/strings.xml
@@ -533,6 +533,8 @@
<string name="accessibility_manual_zen_less_time" msgid="6828877595848229965">"കുറഞ്ഞ സമയം."</string>
<string name="cancel" msgid="5665114069455378395">"റദ്ദാക്കുക"</string>
<string name="okay" msgid="949938843324579502">"ശരി"</string>
+ <!-- no translation found for done (381184316122520313) -->
+ <skip />
<string name="alarms_and_reminders_label" msgid="6918395649731424294">"അലാറങ്ങളും റിമെെൻഡറുകളും"</string>
<string name="alarms_and_reminders_switch_title" msgid="4939393911531826222">"അലാറവും റിമെെൻഡറും സജ്ജീകരിക്കാൻ അനുവദിക്കുക"</string>
<string name="alarms_and_reminders_title" msgid="8819933264635406032">"അലാറങ്ങളും റിമെെൻഡറുകളും"</string>
@@ -551,7 +553,9 @@
<string name="zen_mode_duration_always_prompt_title" msgid="3212996860498119555">"എപ്പോഴും ചോദിക്കുക"</string>
<string name="zen_mode_forever" msgid="3339224497605461291">"നിങ്ങൾ ഓഫാക്കുന്നത് വരെ"</string>
<string name="time_unit_just_now" msgid="3006134267292728099">"ഇപ്പോൾ"</string>
- <string name="media_transfer_this_device_name" msgid="2357329267148436433">"ഈ ഫോൺ"</string>
+ <string name="media_transfer_this_device_name" product="default" msgid="2357329267148436433">"ഈ ഫോൺ"</string>
+ <!-- no translation found for media_transfer_this_device_name (3714653244000242800) -->
+ <skip />
<string name="media_transfer_this_phone" msgid="7194341457812151531">"ഈ ഫോൺ"</string>
<string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"കണക്റ്റ് ചെയ്യുന്നതിൽ പ്രശ്നമുണ്ടായി. ഉപകരണം ഓഫാക്കി വീണ്ടും ഓണാക്കുക"</string>
<string name="media_transfer_wired_device_name" msgid="4447880899964056007">"വയർ മുഖേന ബന്ധിപ്പിച്ച ഓഡിയോ ഉപകരണം"</string>
@@ -591,7 +595,9 @@
<string name="user_set_lock_button" msgid="1427128184982594856">"ലോക്ക് സജ്ജീകരിക്കുക"</string>
<string name="user_switch_to_user" msgid="6975428297154968543">"<xliff:g id="USER_NAME">%s</xliff:g> എന്നതിലേക്ക് മാറുക"</string>
<string name="creating_new_user_dialog_message" msgid="7232880257538970375">"പുതിയ ഉപയോക്താവിനെ സൃഷ്ടിക്കുന്നു…"</string>
+ <string name="creating_new_guest_dialog_message" msgid="1114905602181350690">"പുതിയ അതിഥിയെ സൃഷ്ടിക്കുന്നു…"</string>
<string name="add_user_failed" msgid="4809887794313944872">"പുതിയ ഉപയോക്താവിനെ സൃഷ്ടിക്കാനായില്ല"</string>
+ <string name="add_guest_failed" msgid="8074548434469843443">"പുതിയ അതിഥിയെ സൃഷ്ടിക്കാനായില്ല"</string>
<string name="user_nickname" msgid="262624187455825083">"വിളിപ്പേര്"</string>
<string name="guest_new_guest" msgid="3482026122932643557">"അതിഥിയെ ചേർക്കുക"</string>
<string name="guest_exit_guest" msgid="5908239569510734136">"അതിഥിയെ നീക്കം ചെയ്യുക"</string>
@@ -644,4 +650,7 @@
<string name="dream_complication_title_cast_info" msgid="4038776652841885084">"കാസ്റ്റ് വിവരങ്ങൾ"</string>
<string name="avatar_picker_title" msgid="8492884172713170652">"പ്രൊഫൈൽ ചിത്രം തിരഞ്ഞെടുക്കുക"</string>
<string name="default_user_icon_description" msgid="6554047177298972638">"ഡിഫോൾട്ട് ഉപയോക്തൃ ഐക്കൺ"</string>
+ <string name="physical_keyboard_title" msgid="4811935435315835220">"ഫിസിക്കൽ കീബോർഡ്"</string>
+ <string name="keyboard_layout_dialog_title" msgid="3927180147005616290">"കീബോർഡ് ലേഔട്ട് തിരഞ്ഞെടുക്കുക"</string>
+ <string name="keyboard_layout_default_label" msgid="1997292217218546957">"ഡിഫോൾട്ട്"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-mn/strings.xml b/packages/SettingsLib/res/values-mn/strings.xml
index 7b74da2..fb11d04 100644
--- a/packages/SettingsLib/res/values-mn/strings.xml
+++ b/packages/SettingsLib/res/values-mn/strings.xml
@@ -533,6 +533,8 @@
<string name="accessibility_manual_zen_less_time" msgid="6828877595848229965">"Бага хугацаа."</string>
<string name="cancel" msgid="5665114069455378395">"Цуцлах"</string>
<string name="okay" msgid="949938843324579502">"OK"</string>
+ <!-- no translation found for done (381184316122520313) -->
+ <skip />
<string name="alarms_and_reminders_label" msgid="6918395649731424294">"Сэрүүлэг болон сануулагч"</string>
<string name="alarms_and_reminders_switch_title" msgid="4939393911531826222">"Сэрүүлэг болон сануулагч тохируулахыг зөвшөөрөх"</string>
<string name="alarms_and_reminders_title" msgid="8819933264635406032">"Сэрүүлэг, сануулагч"</string>
@@ -551,7 +553,9 @@
<string name="zen_mode_duration_always_prompt_title" msgid="3212996860498119555">"Тухай бүрд асуух"</string>
<string name="zen_mode_forever" msgid="3339224497605461291">"Таныг унтраах хүртэл"</string>
<string name="time_unit_just_now" msgid="3006134267292728099">"Дөнгөж сая"</string>
- <string name="media_transfer_this_device_name" msgid="2357329267148436433">"Энэ утас"</string>
+ <string name="media_transfer_this_device_name" product="default" msgid="2357329267148436433">"Энэ утас"</string>
+ <!-- no translation found for media_transfer_this_device_name (3714653244000242800) -->
+ <skip />
<string name="media_transfer_this_phone" msgid="7194341457812151531">"Энэ утас"</string>
<string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"Холбогдоход асуудал гарлаа. Төхөөрөмжийг унтраагаад дахин асаана уу"</string>
<string name="media_transfer_wired_device_name" msgid="4447880899964056007">"Утастай аудио төхөөрөмж"</string>
@@ -591,7 +595,9 @@
<string name="user_set_lock_button" msgid="1427128184982594856">"Түгжээг тохируулах"</string>
<string name="user_switch_to_user" msgid="6975428297154968543">"<xliff:g id="USER_NAME">%s</xliff:g> руу сэлгэх"</string>
<string name="creating_new_user_dialog_message" msgid="7232880257538970375">"Шинэ хэрэглэгч үүсгэж байна…"</string>
+ <string name="creating_new_guest_dialog_message" msgid="1114905602181350690">"Шинэ зочин үүсгэж байна…"</string>
<string name="add_user_failed" msgid="4809887794313944872">"Шинэ хэрэглэгч үүсгэж чадсангүй"</string>
+ <string name="add_guest_failed" msgid="8074548434469843443">"Шинэ зочин үүсгэж чадсангүй"</string>
<string name="user_nickname" msgid="262624187455825083">"Хоч"</string>
<string name="guest_new_guest" msgid="3482026122932643557">"Зочин нэмэх"</string>
<string name="guest_exit_guest" msgid="5908239569510734136">"Зочин хасах"</string>
@@ -644,4 +650,7 @@
<string name="dream_complication_title_cast_info" msgid="4038776652841885084">"Дамжуулах мэдээлэл"</string>
<string name="avatar_picker_title" msgid="8492884172713170652">"Профайл зураг сонгох"</string>
<string name="default_user_icon_description" msgid="6554047177298972638">"Өгөгдмөл хэрэглэгчийн дүрс тэмдэг"</string>
+ <string name="physical_keyboard_title" msgid="4811935435315835220">"Биет гар"</string>
+ <string name="keyboard_layout_dialog_title" msgid="3927180147005616290">"Гарын бүдүүвчийг сонгох"</string>
+ <string name="keyboard_layout_default_label" msgid="1997292217218546957">"Өгөгдмөл"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-mr/strings.xml b/packages/SettingsLib/res/values-mr/strings.xml
index 451d834..52aa9c6 100644
--- a/packages/SettingsLib/res/values-mr/strings.xml
+++ b/packages/SettingsLib/res/values-mr/strings.xml
@@ -533,6 +533,8 @@
<string name="accessibility_manual_zen_less_time" msgid="6828877595848229965">"कमी वेळ."</string>
<string name="cancel" msgid="5665114069455378395">"रद्द करा"</string>
<string name="okay" msgid="949938843324579502">"ठीक आहे"</string>
+ <!-- no translation found for done (381184316122520313) -->
+ <skip />
<string name="alarms_and_reminders_label" msgid="6918395649731424294">"अलार्म आणि रिमाइंडर"</string>
<string name="alarms_and_reminders_switch_title" msgid="4939393911531826222">"अलार्म आणि रिमाइंडर सेट करण्याची अनुमती द्या"</string>
<string name="alarms_and_reminders_title" msgid="8819933264635406032">"अलार्म आणि रिमाइंडर"</string>
@@ -551,7 +553,9 @@
<string name="zen_mode_duration_always_prompt_title" msgid="3212996860498119555">"प्रत्येक वेळी विचारा"</string>
<string name="zen_mode_forever" msgid="3339224497605461291">"तुम्ही बंद करेपर्यंत"</string>
<string name="time_unit_just_now" msgid="3006134267292728099">"आत्ताच"</string>
- <string name="media_transfer_this_device_name" msgid="2357329267148436433">"हा फोन"</string>
+ <string name="media_transfer_this_device_name" product="default" msgid="2357329267148436433">"हा फोन"</string>
+ <!-- no translation found for media_transfer_this_device_name (3714653244000242800) -->
+ <skip />
<string name="media_transfer_this_phone" msgid="7194341457812151531">"हा फोन"</string>
<string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"कनेक्ट करण्यात समस्या आली. डिव्हाइस बंद करा आणि नंतर सुरू करा"</string>
<string name="media_transfer_wired_device_name" msgid="4447880899964056007">"वायर असलेले ऑडिओ डिव्हाइस"</string>
@@ -591,7 +595,9 @@
<string name="user_set_lock_button" msgid="1427128184982594856">"लॉक सेट करा"</string>
<string name="user_switch_to_user" msgid="6975428297154968543">"<xliff:g id="USER_NAME">%s</xliff:g> वर स्विच करा"</string>
<string name="creating_new_user_dialog_message" msgid="7232880257538970375">"नवीन वापरकर्ता तयार करत आहे…"</string>
+ <string name="creating_new_guest_dialog_message" msgid="1114905602181350690">"नवीन अतिथी तयार करत आहे…"</string>
<string name="add_user_failed" msgid="4809887794313944872">"नवीन वापरकर्ता तयार करता आला नाही"</string>
+ <string name="add_guest_failed" msgid="8074548434469843443">"नवीन अतिथी तयार करता आला नाही"</string>
<string name="user_nickname" msgid="262624187455825083">"टोपणनाव"</string>
<string name="guest_new_guest" msgid="3482026122932643557">"अतिथी जोडा"</string>
<string name="guest_exit_guest" msgid="5908239569510734136">"अतिथी काढून टाका"</string>
@@ -644,4 +650,7 @@
<string name="dream_complication_title_cast_info" msgid="4038776652841885084">"कास्टसंबंधित माहिती"</string>
<string name="avatar_picker_title" msgid="8492884172713170652">"प्रोफाइल फोटो निवडा"</string>
<string name="default_user_icon_description" msgid="6554047177298972638">"डीफॉल्ट वापरकर्ता आयकन"</string>
+ <string name="physical_keyboard_title" msgid="4811935435315835220">"वास्तविक कीबोर्ड"</string>
+ <string name="keyboard_layout_dialog_title" msgid="3927180147005616290">"किबोर्ड लेआउट निवडा"</string>
+ <string name="keyboard_layout_default_label" msgid="1997292217218546957">"डीफॉल्ट"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-ms/strings.xml b/packages/SettingsLib/res/values-ms/strings.xml
index d3dfb62..7c96e99 100644
--- a/packages/SettingsLib/res/values-ms/strings.xml
+++ b/packages/SettingsLib/res/values-ms/strings.xml
@@ -533,6 +533,8 @@
<string name="accessibility_manual_zen_less_time" msgid="6828877595848229965">"Kurang masa."</string>
<string name="cancel" msgid="5665114069455378395">"Batal"</string>
<string name="okay" msgid="949938843324579502">"OK"</string>
+ <!-- no translation found for done (381184316122520313) -->
+ <skip />
<string name="alarms_and_reminders_label" msgid="6918395649731424294">"Penggera dan peringatan"</string>
<string name="alarms_and_reminders_switch_title" msgid="4939393911531826222">"Benarkan penetapan penggera dan peringatan"</string>
<string name="alarms_and_reminders_title" msgid="8819933264635406032">"Penggera & peringatan"</string>
@@ -551,7 +553,9 @@
<string name="zen_mode_duration_always_prompt_title" msgid="3212996860498119555">"Tanya setiap kali"</string>
<string name="zen_mode_forever" msgid="3339224497605461291">"Sehingga anda matikan"</string>
<string name="time_unit_just_now" msgid="3006134267292728099">"Sebentar tadi"</string>
- <string name="media_transfer_this_device_name" msgid="2357329267148436433">"Telefon ini"</string>
+ <string name="media_transfer_this_device_name" product="default" msgid="2357329267148436433">"Telefon ini"</string>
+ <!-- no translation found for media_transfer_this_device_name (3714653244000242800) -->
+ <skip />
<string name="media_transfer_this_phone" msgid="7194341457812151531">"Telefon ini"</string>
<string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"Masalah penyambungan. Matikan & hidupkan kembali peranti"</string>
<string name="media_transfer_wired_device_name" msgid="4447880899964056007">"Peranti audio berwayar"</string>
@@ -591,7 +595,9 @@
<string name="user_set_lock_button" msgid="1427128184982594856">"Tetapkan kunci"</string>
<string name="user_switch_to_user" msgid="6975428297154968543">"Tukar kepada <xliff:g id="USER_NAME">%s</xliff:g>"</string>
<string name="creating_new_user_dialog_message" msgid="7232880257538970375">"Mencipta pengguna baharu…"</string>
+ <string name="creating_new_guest_dialog_message" msgid="1114905602181350690">"Membuat tetamu baharu…"</string>
<string name="add_user_failed" msgid="4809887794313944872">"Gagal membuat pengguna baharu"</string>
+ <string name="add_guest_failed" msgid="8074548434469843443">"Gagal membuat tetamu baharu"</string>
<string name="user_nickname" msgid="262624187455825083">"Nama panggilan"</string>
<string name="guest_new_guest" msgid="3482026122932643557">"Tambah tetamu"</string>
<string name="guest_exit_guest" msgid="5908239569510734136">"Alih keluar tetamu"</string>
@@ -644,4 +650,7 @@
<string name="dream_complication_title_cast_info" msgid="4038776652841885084">"Maklumat Pelakon"</string>
<string name="avatar_picker_title" msgid="8492884172713170652">"Pilih gambar profil"</string>
<string name="default_user_icon_description" msgid="6554047177298972638">"Ikon pengguna lalai"</string>
+ <string name="physical_keyboard_title" msgid="4811935435315835220">"Papan kekunci fizikal"</string>
+ <string name="keyboard_layout_dialog_title" msgid="3927180147005616290">"Pilih susun atur papan kekunci"</string>
+ <string name="keyboard_layout_default_label" msgid="1997292217218546957">"Lalai"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-my/strings.xml b/packages/SettingsLib/res/values-my/strings.xml
index cc6269f..6fd1d8b 100644
--- a/packages/SettingsLib/res/values-my/strings.xml
+++ b/packages/SettingsLib/res/values-my/strings.xml
@@ -533,6 +533,8 @@
<string name="accessibility_manual_zen_less_time" msgid="6828877595848229965">"အချိန်လျှော့ရန်။"</string>
<string name="cancel" msgid="5665114069455378395">"မလုပ်တော့"</string>
<string name="okay" msgid="949938843324579502">"OK"</string>
+ <!-- no translation found for done (381184316122520313) -->
+ <skip />
<string name="alarms_and_reminders_label" msgid="6918395649731424294">"နှိုးစက်နှင့် သတိပေးချက်များ"</string>
<string name="alarms_and_reminders_switch_title" msgid="4939393911531826222">"နှိုးစက်နှင့် သတိပေးချက်များ သတ်မှတ်ခွင့်ပြုရန်"</string>
<string name="alarms_and_reminders_title" msgid="8819933264635406032">"နှိုးစက်နှင့် သတိပေးချက်များ"</string>
@@ -551,7 +553,9 @@
<string name="zen_mode_duration_always_prompt_title" msgid="3212996860498119555">"အမြဲမေးရန်"</string>
<string name="zen_mode_forever" msgid="3339224497605461291">"သင်ပိတ်လိုက်သည် အထိ"</string>
<string name="time_unit_just_now" msgid="3006134267292728099">"ယခုလေးတင်"</string>
- <string name="media_transfer_this_device_name" msgid="2357329267148436433">"ဤဖုန်း"</string>
+ <string name="media_transfer_this_device_name" product="default" msgid="2357329267148436433">"ဤဖုန်း"</string>
+ <!-- no translation found for media_transfer_this_device_name (3714653244000242800) -->
+ <skip />
<string name="media_transfer_this_phone" msgid="7194341457812151531">"ဤဖုန်း"</string>
<string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"ချိတ်ဆက်ရာတွင် ပြဿနာရှိပါသည်။ စက်ကိုပိတ်ပြီး ပြန်ဖွင့်ပါ"</string>
<string name="media_transfer_wired_device_name" msgid="4447880899964056007">"ကြိုးတပ် အသံစက်ပစ္စည်း"</string>
@@ -591,7 +595,9 @@
<string name="user_set_lock_button" msgid="1427128184982594856">"သော့ချရန် သတ်မှတ်ပါ"</string>
<string name="user_switch_to_user" msgid="6975428297154968543">"<xliff:g id="USER_NAME">%s</xliff:g> သို့ ပြောင်းရန်"</string>
<string name="creating_new_user_dialog_message" msgid="7232880257538970375">"အသုံးပြုသူအသစ် ပြုလုပ်နေသည်…"</string>
+ <string name="creating_new_guest_dialog_message" msgid="1114905602181350690">"ဧည့်သည်သစ် ပြုလုပ်နေသည်…"</string>
<string name="add_user_failed" msgid="4809887794313944872">"အသုံးပြုသူအသစ် ပြုလုပ်၍မရပါ"</string>
+ <string name="add_guest_failed" msgid="8074548434469843443">"ဧည့်သည်သစ် ပြုလုပ်၍မရပါ"</string>
<string name="user_nickname" msgid="262624187455825083">"နာမည်ပြောင်"</string>
<string name="guest_new_guest" msgid="3482026122932643557">"ဧည့်သည့် ထည့်ရန်"</string>
<string name="guest_exit_guest" msgid="5908239569510734136">"ဧည့်သည်ကို ဖယ်ထုတ်ရန်"</string>
@@ -644,4 +650,7 @@
<string name="dream_complication_title_cast_info" msgid="4038776652841885084">"ကာစ် အချက်အလက်"</string>
<string name="avatar_picker_title" msgid="8492884172713170652">"ပရိုဖိုင်ပုံ ရွေးပါ"</string>
<string name="default_user_icon_description" msgid="6554047177298972638">"မူရင်းအသုံးပြုသူ သင်္ကေတ"</string>
+ <string name="physical_keyboard_title" msgid="4811935435315835220">"ပကတိ ကီးဘုတ်"</string>
+ <string name="keyboard_layout_dialog_title" msgid="3927180147005616290">"လက်ကွက်အပြင်အဆင်ရွေးချယ်ခြင်း"</string>
+ <string name="keyboard_layout_default_label" msgid="1997292217218546957">"မူရင်း"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-nb/strings.xml b/packages/SettingsLib/res/values-nb/strings.xml
index 8900fe7..e965d60 100644
--- a/packages/SettingsLib/res/values-nb/strings.xml
+++ b/packages/SettingsLib/res/values-nb/strings.xml
@@ -533,6 +533,8 @@
<string name="accessibility_manual_zen_less_time" msgid="6828877595848229965">"Mindre tid."</string>
<string name="cancel" msgid="5665114069455378395">"Avbryt"</string>
<string name="okay" msgid="949938843324579502">"OK"</string>
+ <!-- no translation found for done (381184316122520313) -->
+ <skip />
<string name="alarms_and_reminders_label" msgid="6918395649731424294">"Alarmer og påminnelser"</string>
<string name="alarms_and_reminders_switch_title" msgid="4939393911531826222">"Tillat innstilling av alarmer og påminnelser"</string>
<string name="alarms_and_reminders_title" msgid="8819933264635406032">"Alarmer og påminnelser"</string>
@@ -551,7 +553,9 @@
<string name="zen_mode_duration_always_prompt_title" msgid="3212996860498119555">"Spør hver gang"</string>
<string name="zen_mode_forever" msgid="3339224497605461291">"Til du slår av"</string>
<string name="time_unit_just_now" msgid="3006134267292728099">"Nå nettopp"</string>
- <string name="media_transfer_this_device_name" msgid="2357329267148436433">"Denne telefonen"</string>
+ <string name="media_transfer_this_device_name" product="default" msgid="2357329267148436433">"Denne telefonen"</string>
+ <!-- no translation found for media_transfer_this_device_name (3714653244000242800) -->
+ <skip />
<string name="media_transfer_this_phone" msgid="7194341457812151531">"Denne telefonen"</string>
<string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"Tilkoblingsproblemer. Slå enheten av og på igjen"</string>
<string name="media_transfer_wired_device_name" msgid="4447880899964056007">"Lydenhet med kabel"</string>
@@ -591,7 +595,9 @@
<string name="user_set_lock_button" msgid="1427128184982594856">"Angi lås"</string>
<string name="user_switch_to_user" msgid="6975428297154968543">"Bytt til <xliff:g id="USER_NAME">%s</xliff:g>"</string>
<string name="creating_new_user_dialog_message" msgid="7232880257538970375">"Oppretter en ny bruker …"</string>
+ <string name="creating_new_guest_dialog_message" msgid="1114905602181350690">"Oppretter en ny gjest …"</string>
<string name="add_user_failed" msgid="4809887794313944872">"Kunne ikke opprette noen ny bruker"</string>
+ <string name="add_guest_failed" msgid="8074548434469843443">"Kunne ikke opprette en ny gjest"</string>
<string name="user_nickname" msgid="262624187455825083">"Kallenavn"</string>
<string name="guest_new_guest" msgid="3482026122932643557">"Legg til en gjest"</string>
<string name="guest_exit_guest" msgid="5908239569510734136">"Fjern gjesten"</string>
@@ -644,4 +650,7 @@
<string name="dream_complication_title_cast_info" msgid="4038776652841885084">"Castinformasjon"</string>
<string name="avatar_picker_title" msgid="8492884172713170652">"Velg et profilbilde"</string>
<string name="default_user_icon_description" msgid="6554047177298972638">"Standard brukerikon"</string>
+ <string name="physical_keyboard_title" msgid="4811935435315835220">"Fysisk tastatur"</string>
+ <string name="keyboard_layout_dialog_title" msgid="3927180147005616290">"Velg et tastaturoppsett"</string>
+ <string name="keyboard_layout_default_label" msgid="1997292217218546957">"Standard"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-ne/strings.xml b/packages/SettingsLib/res/values-ne/strings.xml
index d0270a9..3bcc65a 100644
--- a/packages/SettingsLib/res/values-ne/strings.xml
+++ b/packages/SettingsLib/res/values-ne/strings.xml
@@ -533,6 +533,8 @@
<string name="accessibility_manual_zen_less_time" msgid="6828877595848229965">"कम समय।"</string>
<string name="cancel" msgid="5665114069455378395">"रद्द गर्नुहोस्"</string>
<string name="okay" msgid="949938843324579502">"ठिक छ"</string>
+ <!-- no translation found for done (381184316122520313) -->
+ <skip />
<string name="alarms_and_reminders_label" msgid="6918395649731424294">"अलार्म र रिमाइन्डरहरू"</string>
<string name="alarms_and_reminders_switch_title" msgid="4939393911531826222">"अलार्म तथा रिमाइन्डर सेट गर्न दिइयोस्"</string>
<string name="alarms_and_reminders_title" msgid="8819933264635406032">"घडी तथा रिमाइन्डरहरू"</string>
@@ -551,7 +553,9 @@
<string name="zen_mode_duration_always_prompt_title" msgid="3212996860498119555">"प्रत्येक पटक सोधियोस्"</string>
<string name="zen_mode_forever" msgid="3339224497605461291">"तपाईंले अफ नगरेसम्म"</string>
<string name="time_unit_just_now" msgid="3006134267292728099">"अहिले भर्खरै"</string>
- <string name="media_transfer_this_device_name" msgid="2357329267148436433">"यो फोन"</string>
+ <string name="media_transfer_this_device_name" product="default" msgid="2357329267148436433">"यो फोन"</string>
+ <!-- no translation found for media_transfer_this_device_name (3714653244000242800) -->
+ <skip />
<string name="media_transfer_this_phone" msgid="7194341457812151531">"यो फोन"</string>
<string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"जोड्ने क्रममा समस्या भयो। यन्त्रलाई निष्क्रिय पारेर फेरि सक्रिय गर्नुहोस्"</string>
<string name="media_transfer_wired_device_name" msgid="4447880899964056007">"तारयुक्त अडियो यन्त्र"</string>
@@ -591,7 +595,9 @@
<string name="user_set_lock_button" msgid="1427128184982594856">"लक सेट गर्नुहोस्"</string>
<string name="user_switch_to_user" msgid="6975428297154968543">"प्रयोगकर्ता बदलेर <xliff:g id="USER_NAME">%s</xliff:g> पार्नुहोस्"</string>
<string name="creating_new_user_dialog_message" msgid="7232880257538970375">"नयाँ प्रयोगकर्ता बनाउँदै…"</string>
+ <string name="creating_new_guest_dialog_message" msgid="1114905602181350690">"नयाँ अतिथि बनाइँदै छ…"</string>
<string name="add_user_failed" msgid="4809887794313944872">"नयाँ प्रयोगकर्ता सिर्जना गर्न सकिएन"</string>
+ <string name="add_guest_failed" msgid="8074548434469843443">"नयाँ अतिथि बनाउन सकिएन"</string>
<string name="user_nickname" msgid="262624187455825083">"उपनाम"</string>
<string name="guest_new_guest" msgid="3482026122932643557">"अतिथि थप्नुहोस्"</string>
<string name="guest_exit_guest" msgid="5908239569510734136">"अतिथि हटाउनुहोस्"</string>
@@ -644,4 +650,7 @@
<string name="dream_complication_title_cast_info" msgid="4038776652841885084">"कास्टसम्बन्धी जानकारी"</string>
<string name="avatar_picker_title" msgid="8492884172713170652">"प्रोफाइल फोटो छान्नुहोस्"</string>
<string name="default_user_icon_description" msgid="6554047177298972638">"प्रयोगकर्ताको डिफल्ट आइकन"</string>
+ <string name="physical_keyboard_title" msgid="4811935435315835220">"भौतिक किबोर्ड"</string>
+ <string name="keyboard_layout_dialog_title" msgid="3927180147005616290">"किबोर्ड लेआउट छान्नुहोस्"</string>
+ <string name="keyboard_layout_default_label" msgid="1997292217218546957">"डिफल्ट"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-nl/strings.xml b/packages/SettingsLib/res/values-nl/strings.xml
index 5c19a72..3d14776 100644
--- a/packages/SettingsLib/res/values-nl/strings.xml
+++ b/packages/SettingsLib/res/values-nl/strings.xml
@@ -533,6 +533,8 @@
<string name="accessibility_manual_zen_less_time" msgid="6828877595848229965">"Minder tijd."</string>
<string name="cancel" msgid="5665114069455378395">"Annuleren"</string>
<string name="okay" msgid="949938843324579502">"OK"</string>
+ <!-- no translation found for done (381184316122520313) -->
+ <skip />
<string name="alarms_and_reminders_label" msgid="6918395649731424294">"Wekkers en herinneringen"</string>
<string name="alarms_and_reminders_switch_title" msgid="4939393911531826222">"Wekkers en herinneringen laten instellen"</string>
<string name="alarms_and_reminders_title" msgid="8819933264635406032">"Wekkers en herinneringen"</string>
@@ -551,7 +553,9 @@
<string name="zen_mode_duration_always_prompt_title" msgid="3212996860498119555">"Vraag altijd"</string>
<string name="zen_mode_forever" msgid="3339224497605461291">"Totdat je uitzet"</string>
<string name="time_unit_just_now" msgid="3006134267292728099">"Zojuist"</string>
- <string name="media_transfer_this_device_name" msgid="2357329267148436433">"Deze telefoon"</string>
+ <string name="media_transfer_this_device_name" product="default" msgid="2357329267148436433">"Deze telefoon"</string>
+ <!-- no translation found for media_transfer_this_device_name (3714653244000242800) -->
+ <skip />
<string name="media_transfer_this_phone" msgid="7194341457812151531">"Deze telefoon"</string>
<string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"Probleem bij verbinding maken. Zet het apparaat uit en weer aan."</string>
<string name="media_transfer_wired_device_name" msgid="4447880899964056007">"Bedraad audioapparaat"</string>
@@ -591,7 +595,9 @@
<string name="user_set_lock_button" msgid="1427128184982594856">"Vergrendeling instellen"</string>
<string name="user_switch_to_user" msgid="6975428297154968543">"Overschakelen naar <xliff:g id="USER_NAME">%s</xliff:g>"</string>
<string name="creating_new_user_dialog_message" msgid="7232880257538970375">"Nieuwe gebruiker maken…"</string>
+ <string name="creating_new_guest_dialog_message" msgid="1114905602181350690">"Nieuwe gast maken…"</string>
<string name="add_user_failed" msgid="4809887794313944872">"Kan geen nieuwe gebruiker maken"</string>
+ <string name="add_guest_failed" msgid="8074548434469843443">"Kan geen nieuwe gast maken"</string>
<string name="user_nickname" msgid="262624187455825083">"Bijnaam"</string>
<string name="guest_new_guest" msgid="3482026122932643557">"Gast toevoegen"</string>
<string name="guest_exit_guest" msgid="5908239569510734136">"Gast verwijderen"</string>
@@ -644,4 +650,7 @@
<string name="dream_complication_title_cast_info" msgid="4038776652841885084">"Castinformatie"</string>
<string name="avatar_picker_title" msgid="8492884172713170652">"Kies een profielfoto"</string>
<string name="default_user_icon_description" msgid="6554047177298972638">"Standaard gebruikersicoon"</string>
+ <string name="physical_keyboard_title" msgid="4811935435315835220">"Fysiek toetsenbord"</string>
+ <string name="keyboard_layout_dialog_title" msgid="3927180147005616290">"Toetsenbordindeling kiezen"</string>
+ <string name="keyboard_layout_default_label" msgid="1997292217218546957">"Standaard"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-or/strings.xml b/packages/SettingsLib/res/values-or/strings.xml
index 14abf05..f9ee66c 100644
--- a/packages/SettingsLib/res/values-or/strings.xml
+++ b/packages/SettingsLib/res/values-or/strings.xml
@@ -207,8 +207,8 @@
<string name="tts_status_requires_network" msgid="8327617638884678896">"<xliff:g id="LOCALE">%1$s</xliff:g> ନେଟ୍ୱର୍କ ସଂଯୋଜନା ଆବଶ୍ୟକ କରେ"</string>
<string name="tts_status_not_supported" msgid="2702997696245523743">"<xliff:g id="LOCALE">%1$s</xliff:g> ସପୋର୍ଟ କରୁ ନାହିଁ"</string>
<string name="tts_status_checking" msgid="8026559918948285013">"ଯାଞ୍ଚ କରାଯାଉଛି…"</string>
- <string name="tts_engine_settings_title" msgid="7849477533103566291">"<xliff:g id="TTS_ENGINE_NAME">%s</xliff:g> ପାଇଁ ସେଟିଙ୍ଗ"</string>
- <string name="tts_engine_settings_button" msgid="477155276199968948">"ଇଞ୍ଜିନ୍ ସେଟିଙ୍ଗ ଆରମ୍ଭ କରନ୍ତୁ"</string>
+ <string name="tts_engine_settings_title" msgid="7849477533103566291">"<xliff:g id="TTS_ENGINE_NAME">%s</xliff:g> ପାଇଁ ସେଟିଂସ"</string>
+ <string name="tts_engine_settings_button" msgid="477155276199968948">"ଇଞ୍ଜିନ୍ ସେଟିଂସ ଲଞ୍ଚ କରନ୍ତୁ"</string>
<string name="tts_engine_preference_section_title" msgid="3861562305498624904">"ନିଜ ପସନ୍ଦର ଇଞ୍ଜିନ୍"</string>
<string name="tts_general_section_title" msgid="8919671529502364567">"ସାଧାରଣ"</string>
<string name="tts_reset_speech_pitch_title" msgid="7149398585468413246">"ସ୍ପୀଚ୍ର ପିଚ୍ ରିସେଟ୍ କରନ୍ତୁ"</string>
@@ -231,9 +231,9 @@
<string name="development_settings_enable" msgid="4285094651288242183">"ଡେଭଲପର୍ ବିକଳ୍ପଗୁଡ଼ିକ ସକ୍ଷମ କରନ୍ତୁ"</string>
<string name="development_settings_summary" msgid="8718917813868735095">"ଆପ୍ର ବିକାଶ ପାଇଁ ବିକଳ୍ପମାନ ସେଟ୍ କରନ୍ତୁ"</string>
<string name="development_settings_not_available" msgid="355070198089140951">"ଏହି ଉପଯୋଗକର୍ତ୍ତାଙ୍କ ପାଇଁ ଡେଭଲପରଙ୍କ ବିକଳ୍ପସମୂହ ଉପଲବ୍ଧ ନୁହେଁ"</string>
- <string name="vpn_settings_not_available" msgid="2894137119965668920">"VPN ସେଟିଙ୍ଗ ଏହି ଉପଯୋଗକର୍ତ୍ତାଙ୍କ ପାଇଁ ଉପଲବ୍ଧ ନୁହେଁ"</string>
- <string name="tethering_settings_not_available" msgid="266821736434699780">"ଏହି ଉପଯୋଗକର୍ତ୍ତାଙ୍କ ପାଇଁ ଟିଥରିଙ୍ଗ ସେଟିଙ୍ଗ ଉପଲବ୍ଧ ନାହିଁ"</string>
- <string name="apn_settings_not_available" msgid="1147111671403342300">"ଆକ୍ସେସ୍ ପଏଣ୍ଟ ନାମର ସେଟିଙ୍ଗ ଏହି ଉପଯୋଗକର୍ତ୍ତାଙ୍କ ପାଇଁ ଉପଲବ୍ଧ ନାହିଁ"</string>
+ <string name="vpn_settings_not_available" msgid="2894137119965668920">"VPN ସେଟିଂସ ଏହି ଉପଯୋଗକର୍ତ୍ତାଙ୍କ ପାଇଁ ଉପଲବ୍ଧ ନାହିଁ"</string>
+ <string name="tethering_settings_not_available" msgid="266821736434699780">"ଏହି ଉପଯୋଗକର୍ତ୍ତାଙ୍କ ପାଇଁ ଟିଥରିଂ ସେଟିଂସ ଉପଲବ୍ଧ ନାହିଁ"</string>
+ <string name="apn_settings_not_available" msgid="1147111671403342300">"ଆକ୍ସେସ ପଏଣ୍ଟ ନାମର ସେଟିଂସ ଏହି ଉପଯୋଗକର୍ତ୍ତାଙ୍କ ପାଇଁ ଉପଲବ୍ଧ ନାହିଁ"</string>
<string name="enable_adb" msgid="8072776357237289039">"USB ଡିବଗିଂ"</string>
<string name="enable_adb_summary" msgid="3711526030096574316">"USB ସଂଯୁକ୍ତ ହେବାବେଳେ ଡିବଗ୍ ମୋଡ୍"</string>
<string name="clear_adb_keys" msgid="3010148733140369917">"USB ଡିବଗିଂ ଅଧିକାରକୁ ବାତିଲ୍ କରନ୍ତୁ"</string>
@@ -335,8 +335,8 @@
<string name="adbwifi_warning_title" msgid="727104571653031865">"ୱାୟାରଲେସ୍ ଡିବଗିଂ ପାଇଁ ଅନୁମତି ଦେବେ?"</string>
<string name="adbwifi_warning_message" msgid="8005936574322702388">"ୱାୟାରଲେସ୍ ଡିବଗିଂ କେବଳ ଉନ୍ନତି ପାଇଁ ଉଦ୍ଦିଷ୍ଟ ଅଟେ। ଆପଣଙ୍କ କମ୍ପ୍ୟୁଟର ଏବଂ ଡିଭାଇସ୍ ମଧ୍ୟରେ ଡାଟା କପି କରିବାକୁ, ବିନା ବିଜ୍ଞପ୍ତିରେ ଆପଣଙ୍କ ଡିଭାଇସରେ ଆପ୍ସ ଇନଷ୍ଟଲ୍ କରିବାକୁ ଏବଂ ଲଗ୍ ଡାଟା ପଢ଼ିବା ପାଇଁ ଏହାକୁ ବ୍ୟବହାର କରନ୍ତୁ।"</string>
<string name="adb_keys_warning_message" msgid="2968555274488101220">"ଅଧିକୃତ ସମସ୍ତ କମ୍ପ୍ୟୁଟରରୁ USB ଡିବଗ୍ କରିବା ଆକ୍ସେସ୍ ପ୍ରତ୍ୟାହାର କରିବେ କି?"</string>
- <string name="dev_settings_warning_title" msgid="8251234890169074553">"ଡେଭଲପମେଣ୍ଟ ସେଟିଙ୍ଗ ଅନୁମତି ଦେବେ?"</string>
- <string name="dev_settings_warning_message" msgid="37741686486073668">"ଏହି ସେଟିଙ୍ଗଗୁଡ଼ିକ କେବଳ ବିକାଶ ବ୍ୟବହାର ପାଇଁ ଉଦ୍ଦିଷ୍ଟ। ସେଗୁଡ଼ିକ କାରଣରୁ ଆପଣଙ୍କ ଡିଭାଇସ୍ ଓ ଆପ୍ଲିକେଶନ୍ଗୁଡ଼ିକ ଠିକ୍ ଭାବେ କାମ ନକରିପାରେ।"</string>
+ <string name="dev_settings_warning_title" msgid="8251234890169074553">"ଡେଭଲପମେଣ୍ଟ ସେଟିଂସକୁ ଅନୁମତି ଦେବେ?"</string>
+ <string name="dev_settings_warning_message" msgid="37741686486073668">"ଏହି ସେଟିଂସ କେବଳ ବିକାଶର ବ୍ୟବହାର ପାଇଁ ଉଦ୍ଦିଷ୍ଟ। ସେଗୁଡ଼ିକ କାରଣରୁ ଆପଣଙ୍କ ଡିଭାଇସ ଓ ଆପ୍ଲିକେସନଗୁଡ଼ିକ ଖରାପ ହୋଇଯାଇପାରେ କିମ୍ବା ଠିକ୍ ଭାବେ କାମ ନକରିପାରେ।"</string>
<string name="verify_apps_over_usb_title" msgid="6031809675604442636">"USB ଜରିଆରେ ଆପ୍ଗୁଡ଼ିକୁ ଯାଞ୍ଚ କରନ୍ତୁ"</string>
<string name="verify_apps_over_usb_summary" msgid="1317933737581167839">"ADB/ADT ମାଧ୍ୟମରେ ଇନଷ୍ଟଲ ହୋଇଥିବା ଆପ୍ଗୁଡ଼ିକ କ୍ଷତିକାରକ କି ନୁହେଁ ଯାଞ୍ଚ କରନ୍ତୁ।"</string>
<string name="bluetooth_show_devices_without_names_summary" msgid="780964354377854507">"(କେବଳ MAC ଠିକଣା ଥାଇ) ନାମ ବିନା ବ୍ଲୁଟୂଥ ଡିଭାଇସଗୁଡ଼ିକ ପ୍ରଦର୍ଶିତ ହେବ"</string>
@@ -500,7 +500,7 @@
<string name="external_source_trusted" msgid="1146522036773132905">"ଅନୁମତି ଦିଆଯାଇଛି"</string>
<string name="external_source_untrusted" msgid="5037891688911672227">"ଅନୁମତି ନାହିଁ"</string>
<string name="install_other_apps" msgid="3232595082023199454">"ଅଜଣା ଆପ୍ ଇନଷ୍ଟଲ୍ କରନ୍ତୁ"</string>
- <string name="home" msgid="973834627243661438">"ସେଟିଂସ୍ ହୋମ୍"</string>
+ <string name="home" msgid="973834627243661438">"ସେଟିଂସ ହୋମ"</string>
<string-array name="battery_labels">
<item msgid="7878690469765357158">"0%"</item>
<item msgid="8894873528875953317">"50%"</item>
@@ -520,7 +520,7 @@
<string name="retail_demo_reset_title" msgid="1866911701095959800">"ପାସ୍ୱର୍ଡ ଆବଶ୍ୟକ"</string>
<string name="active_input_method_subtypes" msgid="4232680535471633046">"ସକ୍ରିୟ ଇନପୁଟ୍-ପଦ୍ଧତିଗୁଡ଼ିକ"</string>
<string name="use_system_language_to_select_input_method_subtypes" msgid="4865195835541387040">"ସିଷ୍ଟମ୍ ଭାଷା ବ୍ୟବହାର କରନ୍ତୁ"</string>
- <string name="failed_to_open_app_settings_toast" msgid="764897252657692092">"<xliff:g id="SPELL_APPLICATION_NAME">%1$s</xliff:g> ପାଇଁ ସେଟିଙ୍ଗ ଖୋଲିବାରେ ବିଫଳ"</string>
+ <string name="failed_to_open_app_settings_toast" msgid="764897252657692092">"<xliff:g id="SPELL_APPLICATION_NAME">%1$s</xliff:g> ପାଇଁ ସେଟିଂସ ଖୋଲିବାରେ ବିଫଳ"</string>
<string name="ime_security_warning" msgid="6547562217880551450">"ଏହି ଇନ୍ପୁଟ୍ ପଦ୍ଧତି, ପାସ୍ୱର୍ଡ ଓ କ୍ରେଡିଟ୍ କାର୍ଡ ନମ୍ୱର୍ ଭଳି ବ୍ୟକ୍ତିଗତ ଡାଟା ସମେତ ଆପଣ ଟାଇପ୍ କରିଥିବା ସମସ୍ତ ଅକ୍ଷର ସଂଗହ କରିପାରେ।ଏହା, <xliff:g id="IME_APPLICATION_NAME">%1$s</xliff:g> ଆପ୍ରୁ ଆସିଛି| ଏହି ଇନ୍ପୁଟ୍ ପଦ୍ଧତି ବ୍ୟବହାର କରିବେ?"</string>
<string name="direct_boot_unaware_dialog_message" msgid="7845398276735021548">"ଧ୍ୟାନଦିଅନ୍ତୁ: ରିବୁଟ୍ କରିବା ପରେ, ଆପଣଙ୍କ ଫୋନ୍ ଅନଲକ୍ ନହେବା ପର୍ଯ୍ୟନ୍ତ ଏହି ଆପ୍ ଆରମ୍ଭ ହୋଇପାରିବ ନାହିଁ"</string>
<string name="ims_reg_title" msgid="8197592958123671062">"IMS ପଞ୍ଜିକରଣ ସ୍ଥିତି"</string>
@@ -533,6 +533,8 @@
<string name="accessibility_manual_zen_less_time" msgid="6828877595848229965">"କମ୍ ସମୟ।"</string>
<string name="cancel" msgid="5665114069455378395">"ବାତିଲ୍"</string>
<string name="okay" msgid="949938843324579502">"ଠିକ୍ ଅଛି"</string>
+ <!-- no translation found for done (381184316122520313) -->
+ <skip />
<string name="alarms_and_reminders_label" msgid="6918395649731424294">"ଆଲାରାମ୍ ଏବଂ ରିମାଇଣ୍ଡରଗୁଡ଼ିକ"</string>
<string name="alarms_and_reminders_switch_title" msgid="4939393911531826222">"ଆଲାରାମ ଓ ରିମାଇଣ୍ଡରଗୁଡ଼ିକ ସେଟ କରିବାକୁ ଅନୁମତି ଦିଅନ୍ତୁ"</string>
<string name="alarms_and_reminders_title" msgid="8819933264635406032">"ଆଲାରାମ୍ ଏବଂ ରିମାଇଣ୍ଡରଗୁଡ଼ିକ"</string>
@@ -551,7 +553,9 @@
<string name="zen_mode_duration_always_prompt_title" msgid="3212996860498119555">"ପ୍ରତ୍ୟେକ ଥର ପଚାରନ୍ତୁ"</string>
<string name="zen_mode_forever" msgid="3339224497605461291">"ଆପଣ ବନ୍ଦ ନକରିବା ପର୍ଯ୍ୟନ୍ତ"</string>
<string name="time_unit_just_now" msgid="3006134267292728099">"ଏହିକ୍ଷଣି"</string>
- <string name="media_transfer_this_device_name" msgid="2357329267148436433">"ଏହି ଫୋନ"</string>
+ <string name="media_transfer_this_device_name" product="default" msgid="2357329267148436433">"ଏହି ଫୋନ"</string>
+ <!-- no translation found for media_transfer_this_device_name (3714653244000242800) -->
+ <skip />
<string name="media_transfer_this_phone" msgid="7194341457812151531">"ଏହି ଫୋନ୍"</string>
<string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"ସଂଯୋଗ କରିବାରେ ସମସ୍ୟା ହେଉଛି। ଡିଭାଇସ୍ ବନ୍ଦ କରି ପୁଣି ଚାଲୁ କରନ୍ତୁ"</string>
<string name="media_transfer_wired_device_name" msgid="4447880899964056007">"ତାରଯୁକ୍ତ ଅଡିଓ ଡିଭାଇସ୍"</string>
@@ -591,7 +595,9 @@
<string name="user_set_lock_button" msgid="1427128184982594856">"ଲକ୍ ସେଟ୍ କରନ୍ତୁ"</string>
<string name="user_switch_to_user" msgid="6975428297154968543">"<xliff:g id="USER_NAME">%s</xliff:g>କୁ ସ୍ୱିଚ୍ କରନ୍ତୁ"</string>
<string name="creating_new_user_dialog_message" msgid="7232880257538970375">"ନୂଆ ଉପଯୋଗକର୍ତ୍ତା ତିଆରି କରାଯାଉଛି…"</string>
+ <string name="creating_new_guest_dialog_message" msgid="1114905602181350690">"ନୂଆ ଅତିଥି ତିଆରି କରାଯାଉଛି…"</string>
<string name="add_user_failed" msgid="4809887794313944872">"ନୂଆ ଉପଯୋଗକର୍ତ୍ତା ତିଆରି କରିବାକୁ ବିଫଳ ହେଲା"</string>
+ <string name="add_guest_failed" msgid="8074548434469843443">"ଜଣେ ନୂଆ ଅତିଥି ତିଆରି କରିବାରେ ବିଫଳ ହୋଇଛି"</string>
<string name="user_nickname" msgid="262624187455825083">"ଡାକନାମ"</string>
<string name="guest_new_guest" msgid="3482026122932643557">"ଅତିଥି ଯୋଗ କରନ୍ତୁ"</string>
<string name="guest_exit_guest" msgid="5908239569510734136">"ଅତିଥିଙ୍କୁ କାଢ଼ି ଦିଅନ୍ତୁ"</string>
@@ -644,4 +650,10 @@
<string name="dream_complication_title_cast_info" msgid="4038776652841885084">"କାଷ୍ଟ ସୂଚନା"</string>
<string name="avatar_picker_title" msgid="8492884172713170652">"ଏକ ପ୍ରୋଫାଇଲ ଛବି ବାଛନ୍ତୁ"</string>
<string name="default_user_icon_description" msgid="6554047177298972638">"ଡିଫଲ୍ଟ ଉପଯୋଗକର୍ତ୍ତା ଆଇକନ"</string>
+ <!-- no translation found for physical_keyboard_title (4811935435315835220) -->
+ <skip />
+ <!-- no translation found for keyboard_layout_dialog_title (3927180147005616290) -->
+ <skip />
+ <!-- no translation found for keyboard_layout_default_label (1997292217218546957) -->
+ <skip />
</resources>
diff --git a/packages/SettingsLib/res/values-pa/strings.xml b/packages/SettingsLib/res/values-pa/strings.xml
index 4671454..f1a24e4 100644
--- a/packages/SettingsLib/res/values-pa/strings.xml
+++ b/packages/SettingsLib/res/values-pa/strings.xml
@@ -533,6 +533,8 @@
<string name="accessibility_manual_zen_less_time" msgid="6828877595848229965">"ਘੱਟ ਸਮਾਂ।"</string>
<string name="cancel" msgid="5665114069455378395">"ਰੱਦ ਕਰੋ"</string>
<string name="okay" msgid="949938843324579502">"ਠੀਕ ਹੈ"</string>
+ <!-- no translation found for done (381184316122520313) -->
+ <skip />
<string name="alarms_and_reminders_label" msgid="6918395649731424294">"ਅਲਾਰਮ ਅਤੇ ਰਿਮਾਈਂਡਰ"</string>
<string name="alarms_and_reminders_switch_title" msgid="4939393911531826222">"ਅਲਾਰਮ ਅਤੇ ਰਿਮਾਈਂਡਰ ਸੈੱਟ ਕਰਨ ਦੀ ਆਗਿਆ ਦਿਓ"</string>
<string name="alarms_and_reminders_title" msgid="8819933264635406032">"ਅਲਾਰਮ ਅਤੇ ਰਿਮਾਈਂਡਰ"</string>
@@ -551,7 +553,9 @@
<string name="zen_mode_duration_always_prompt_title" msgid="3212996860498119555">"ਹਰ ਵਾਰ ਪੁੱਛੋ"</string>
<string name="zen_mode_forever" msgid="3339224497605461291">"ਜਦੋਂ ਤੱਕ ਤੁਸੀਂ ਬੰਦ ਨਹੀਂ ਕਰਦੇ"</string>
<string name="time_unit_just_now" msgid="3006134267292728099">"ਹੁਣੇ ਹੀ"</string>
- <string name="media_transfer_this_device_name" msgid="2357329267148436433">"ਇਹ ਫ਼ੋਨ"</string>
+ <string name="media_transfer_this_device_name" product="default" msgid="2357329267148436433">"ਇਹ ਫ਼ੋਨ"</string>
+ <!-- no translation found for media_transfer_this_device_name (3714653244000242800) -->
+ <skip />
<string name="media_transfer_this_phone" msgid="7194341457812151531">"ਇਹ ਫ਼ੋਨ"</string>
<string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"ਕਨੈਕਟ ਕਰਨ ਵਿੱਚ ਸਮੱਸਿਆ ਆਈ। ਡੀਵਾਈਸ ਨੂੰ ਬੰਦ ਕਰਕੇ ਵਾਪਸ ਚਾਲੂ ਕਰੋ"</string>
<string name="media_transfer_wired_device_name" msgid="4447880899964056007">"ਤਾਰ ਵਾਲਾ ਆਡੀਓ ਡੀਵਾਈਸ"</string>
@@ -591,7 +595,9 @@
<string name="user_set_lock_button" msgid="1427128184982594856">" ਲਾਕ ਸੈੱਟ ਕਰੋ"</string>
<string name="user_switch_to_user" msgid="6975428297154968543">"<xliff:g id="USER_NAME">%s</xliff:g> \'ਤੇ ਜਾਓ"</string>
<string name="creating_new_user_dialog_message" msgid="7232880257538970375">"ਨਵਾਂ ਵਰਤੋਂਕਾਰ ਬਣਾਇਆ ਜਾ ਰਿਹਾ ਹੈ…"</string>
+ <string name="creating_new_guest_dialog_message" msgid="1114905602181350690">"ਨਵਾਂ ਮਹਿਮਾਨ ਪ੍ਰੋਫਾਈਲ ਬਣਾਇਆ ਜਾ ਰਿਹਾ ਹੈ…"</string>
<string name="add_user_failed" msgid="4809887794313944872">"ਨਵਾਂ ਵਰਤੋਂਕਾਰ ਬਣਾਉਣਾ ਅਸਫਲ ਰਿਹਾ"</string>
+ <string name="add_guest_failed" msgid="8074548434469843443">"ਨਵਾਂ ਮਹਿਮਾਨ ਪ੍ਰੋਫਾਈਲ ਬਣਾਉਣਾ ਅਸਫਲ ਰਿਹਾ"</string>
<string name="user_nickname" msgid="262624187455825083">"ਉਪਨਾਮ"</string>
<string name="guest_new_guest" msgid="3482026122932643557">"ਮਹਿਮਾਨ ਸ਼ਾਮਲ ਕਰੋ"</string>
<string name="guest_exit_guest" msgid="5908239569510734136">"ਮਹਿਮਾਨ ਹਟਾਓ"</string>
@@ -644,4 +650,7 @@
<string name="dream_complication_title_cast_info" msgid="4038776652841885084">"ਕਾਸਟ ਸੰਬੰਧੀ ਜਾਣਕਾਰੀ"</string>
<string name="avatar_picker_title" msgid="8492884172713170652">"ਕੋਈ ਪ੍ਰੋਫਾਈਲ ਤਸਵੀਰ ਚੁਣੋ"</string>
<string name="default_user_icon_description" msgid="6554047177298972638">"ਪੂਰਵ-ਨਿਰਧਾਰਿਤ ਵਰਤੋਂਕਾਰ ਪ੍ਰਤੀਕ"</string>
+ <string name="physical_keyboard_title" msgid="4811935435315835220">"ਭੌਤਿਕ ਕੀ-ਬੋਰਡ"</string>
+ <string name="keyboard_layout_dialog_title" msgid="3927180147005616290">"ਕੀ-ਬੋਰਡ ਖਾਕਾ ਚੁਣੋ"</string>
+ <string name="keyboard_layout_default_label" msgid="1997292217218546957">"ਪੂਰਵ-ਨਿਰਧਾਰਿਤ"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-pl/strings.xml b/packages/SettingsLib/res/values-pl/strings.xml
index 073ffbd..852ed6f 100644
--- a/packages/SettingsLib/res/values-pl/strings.xml
+++ b/packages/SettingsLib/res/values-pl/strings.xml
@@ -533,6 +533,8 @@
<string name="accessibility_manual_zen_less_time" msgid="6828877595848229965">"Mniej czasu."</string>
<string name="cancel" msgid="5665114069455378395">"Anuluj"</string>
<string name="okay" msgid="949938843324579502">"OK"</string>
+ <!-- no translation found for done (381184316122520313) -->
+ <skip />
<string name="alarms_and_reminders_label" msgid="6918395649731424294">"Alarmy i przypomnienia"</string>
<string name="alarms_and_reminders_switch_title" msgid="4939393911531826222">"Zezwalaj na ustawianie alarmów i przypomnień"</string>
<string name="alarms_and_reminders_title" msgid="8819933264635406032">"Alarmy i przypomnienia"</string>
@@ -551,7 +553,9 @@
<string name="zen_mode_duration_always_prompt_title" msgid="3212996860498119555">"Zawsze pytaj"</string>
<string name="zen_mode_forever" msgid="3339224497605461291">"Dopóki nie wyłączysz"</string>
<string name="time_unit_just_now" msgid="3006134267292728099">"Przed chwilą"</string>
- <string name="media_transfer_this_device_name" msgid="2357329267148436433">"Ten telefon"</string>
+ <string name="media_transfer_this_device_name" product="default" msgid="2357329267148436433">"Ten telefon"</string>
+ <!-- no translation found for media_transfer_this_device_name (3714653244000242800) -->
+ <skip />
<string name="media_transfer_this_phone" msgid="7194341457812151531">"Ten telefon"</string>
<string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"Problem z połączeniem. Wyłącz i ponownie włącz urządzenie"</string>
<string name="media_transfer_wired_device_name" msgid="4447880899964056007">"Przewodowe urządzenie audio"</string>
@@ -591,7 +595,9 @@
<string name="user_set_lock_button" msgid="1427128184982594856">"Ustaw blokadę"</string>
<string name="user_switch_to_user" msgid="6975428297154968543">"Przełącz na: <xliff:g id="USER_NAME">%s</xliff:g>"</string>
<string name="creating_new_user_dialog_message" msgid="7232880257538970375">"Tworzę nowego użytkownika…"</string>
+ <string name="creating_new_guest_dialog_message" msgid="1114905602181350690">"Tworzę nowego gościa…"</string>
<string name="add_user_failed" msgid="4809887794313944872">"Nie udało się utworzyć nowego użytkownika"</string>
+ <string name="add_guest_failed" msgid="8074548434469843443">"Nie udało się utworzyć nowego gościa"</string>
<string name="user_nickname" msgid="262624187455825083">"Pseudonim"</string>
<string name="guest_new_guest" msgid="3482026122932643557">"Dodaj gościa"</string>
<string name="guest_exit_guest" msgid="5908239569510734136">"Usuń gościa"</string>
@@ -644,4 +650,7 @@
<string name="dream_complication_title_cast_info" msgid="4038776652841885084">"Obsada"</string>
<string name="avatar_picker_title" msgid="8492884172713170652">"Wybierz zdjęcie profilowe"</string>
<string name="default_user_icon_description" msgid="6554047177298972638">"Ikona domyślnego użytkownika"</string>
+ <string name="physical_keyboard_title" msgid="4811935435315835220">"Klawiatura fizyczna"</string>
+ <string name="keyboard_layout_dialog_title" msgid="3927180147005616290">"Wybierz układ klawiatury"</string>
+ <string name="keyboard_layout_default_label" msgid="1997292217218546957">"Domyślny"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-pt-rBR/strings.xml b/packages/SettingsLib/res/values-pt-rBR/strings.xml
index 8d93b31..cdb364a 100644
--- a/packages/SettingsLib/res/values-pt-rBR/strings.xml
+++ b/packages/SettingsLib/res/values-pt-rBR/strings.xml
@@ -533,6 +533,8 @@
<string name="accessibility_manual_zen_less_time" msgid="6828877595848229965">"Menos tempo."</string>
<string name="cancel" msgid="5665114069455378395">"Cancelar"</string>
<string name="okay" msgid="949938843324579502">"Ok"</string>
+ <!-- no translation found for done (381184316122520313) -->
+ <skip />
<string name="alarms_and_reminders_label" msgid="6918395649731424294">"Alarmes e lembretes"</string>
<string name="alarms_and_reminders_switch_title" msgid="4939393911531826222">"Autorizar a definição de alarmes e lembretes"</string>
<string name="alarms_and_reminders_title" msgid="8819933264635406032">"Alarmes e lembretes"</string>
@@ -551,7 +553,9 @@
<string name="zen_mode_duration_always_prompt_title" msgid="3212996860498119555">"Perguntar sempre"</string>
<string name="zen_mode_forever" msgid="3339224497605461291">"Até você desativar"</string>
<string name="time_unit_just_now" msgid="3006134267292728099">"Agora"</string>
- <string name="media_transfer_this_device_name" msgid="2357329267148436433">"Este smartphone"</string>
+ <string name="media_transfer_this_device_name" product="default" msgid="2357329267148436433">"Este smartphone"</string>
+ <!-- no translation found for media_transfer_this_device_name (3714653244000242800) -->
+ <skip />
<string name="media_transfer_this_phone" msgid="7194341457812151531">"Este smartphone"</string>
<string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"Ocorreu um problema na conexão. Desligue o dispositivo e ligue-o novamente"</string>
<string name="media_transfer_wired_device_name" msgid="4447880899964056007">"Dispositivo de áudio com fio"</string>
@@ -591,7 +595,9 @@
<string name="user_set_lock_button" msgid="1427128184982594856">"Definir bloqueio"</string>
<string name="user_switch_to_user" msgid="6975428297154968543">"Mudar para <xliff:g id="USER_NAME">%s</xliff:g>"</string>
<string name="creating_new_user_dialog_message" msgid="7232880257538970375">"Criando novo usuário…"</string>
+ <string name="creating_new_guest_dialog_message" msgid="1114905602181350690">"Criando novo convidado…"</string>
<string name="add_user_failed" msgid="4809887794313944872">"Falha ao criar um novo usuário"</string>
+ <string name="add_guest_failed" msgid="8074548434469843443">"Falha ao criar um novo convidado"</string>
<string name="user_nickname" msgid="262624187455825083">"Apelido"</string>
<string name="guest_new_guest" msgid="3482026122932643557">"Adicionar convidado"</string>
<string name="guest_exit_guest" msgid="5908239569510734136">"Remover convidado"</string>
@@ -644,4 +650,7 @@
<string name="dream_complication_title_cast_info" msgid="4038776652841885084">"Info. de transmissão"</string>
<string name="avatar_picker_title" msgid="8492884172713170652">"Escolher a foto do perfil"</string>
<string name="default_user_icon_description" msgid="6554047177298972638">"Ícone de usuário padrão"</string>
+ <string name="physical_keyboard_title" msgid="4811935435315835220">"Teclado físico"</string>
+ <string name="keyboard_layout_dialog_title" msgid="3927180147005616290">"Escolha o layout do teclado"</string>
+ <string name="keyboard_layout_default_label" msgid="1997292217218546957">"Padrão"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-pt-rPT/strings.xml b/packages/SettingsLib/res/values-pt-rPT/strings.xml
index 47a49e7..c647a21 100644
--- a/packages/SettingsLib/res/values-pt-rPT/strings.xml
+++ b/packages/SettingsLib/res/values-pt-rPT/strings.xml
@@ -528,11 +528,13 @@
<string name="ims_reg_status_not_registered" msgid="2989287366045704694">"Não registado"</string>
<string name="status_unavailable" msgid="5279036186589861608">"Indisponível"</string>
<string name="wifi_status_mac_randomized" msgid="466382542497832189">"O MAC é aleatório."</string>
- <string name="wifi_tether_connected_summary" msgid="5282919920463340158">"{count,plural, =0{0 dispositivo ligados}=1{1 dispositivo ligado}one{# dispositivo(s) ligado(s)}other{# dispositivos ligados}}"</string>
+ <string name="wifi_tether_connected_summary" msgid="5282919920463340158">"{count,plural, =0{0 dispositivo ligados}=1{1 dispositivo ligado}other{# dispositivos ligados}}"</string>
<string name="accessibility_manual_zen_more_time" msgid="5141801092071134235">"Mais tempo."</string>
<string name="accessibility_manual_zen_less_time" msgid="6828877595848229965">"Menos tempo."</string>
<string name="cancel" msgid="5665114069455378395">"Cancelar"</string>
<string name="okay" msgid="949938843324579502">"OK"</string>
+ <!-- no translation found for done (381184316122520313) -->
+ <skip />
<string name="alarms_and_reminders_label" msgid="6918395649731424294">"Alarmes e lembretes"</string>
<string name="alarms_and_reminders_switch_title" msgid="4939393911531826222">"Permitir a definição de alarmes e lembretes"</string>
<string name="alarms_and_reminders_title" msgid="8819933264635406032">"Alarmes e lembretes"</string>
@@ -551,7 +553,9 @@
<string name="zen_mode_duration_always_prompt_title" msgid="3212996860498119555">"Perguntar sempre"</string>
<string name="zen_mode_forever" msgid="3339224497605461291">"Até desativar"</string>
<string name="time_unit_just_now" msgid="3006134267292728099">"Agora mesmo"</string>
- <string name="media_transfer_this_device_name" msgid="2357329267148436433">"Este telemóvel"</string>
+ <string name="media_transfer_this_device_name" product="default" msgid="2357329267148436433">"Este telemóvel"</string>
+ <!-- no translation found for media_transfer_this_device_name (3714653244000242800) -->
+ <skip />
<string name="media_transfer_this_phone" msgid="7194341457812151531">"Este telemóvel"</string>
<string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"Problema ao ligar. Desligue e volte a ligar o dispositivo."</string>
<string name="media_transfer_wired_device_name" msgid="4447880899964056007">"Dispositivo de áudio com fios"</string>
@@ -591,7 +595,9 @@
<string name="user_set_lock_button" msgid="1427128184982594856">"Definir bloqueio"</string>
<string name="user_switch_to_user" msgid="6975428297154968543">"Mudar para <xliff:g id="USER_NAME">%s</xliff:g>"</string>
<string name="creating_new_user_dialog_message" msgid="7232880257538970375">"A criar novo utilizador…"</string>
+ <string name="creating_new_guest_dialog_message" msgid="1114905602181350690">"A criar novo convidado…"</string>
<string name="add_user_failed" msgid="4809887794313944872">"Falha ao criar um novo utilizador"</string>
+ <string name="add_guest_failed" msgid="8074548434469843443">"Falha ao criar um novo convidado"</string>
<string name="user_nickname" msgid="262624187455825083">"Alcunha"</string>
<string name="guest_new_guest" msgid="3482026122932643557">"Adicionar convidado"</string>
<string name="guest_exit_guest" msgid="5908239569510734136">"Remover convidado"</string>
@@ -644,4 +650,7 @@
<string name="dream_complication_title_cast_info" msgid="4038776652841885084">"Info. de transmissão"</string>
<string name="avatar_picker_title" msgid="8492884172713170652">"Escolha uma imagem do perfil"</string>
<string name="default_user_icon_description" msgid="6554047177298972638">"Ícone do utilizador predefinido"</string>
+ <string name="physical_keyboard_title" msgid="4811935435315835220">"Teclado físico"</string>
+ <string name="keyboard_layout_dialog_title" msgid="3927180147005616290">"Escolha um esquema de teclado"</string>
+ <string name="keyboard_layout_default_label" msgid="1997292217218546957">"Predefinição"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-pt/strings.xml b/packages/SettingsLib/res/values-pt/strings.xml
index 8d93b31..cdb364a 100644
--- a/packages/SettingsLib/res/values-pt/strings.xml
+++ b/packages/SettingsLib/res/values-pt/strings.xml
@@ -533,6 +533,8 @@
<string name="accessibility_manual_zen_less_time" msgid="6828877595848229965">"Menos tempo."</string>
<string name="cancel" msgid="5665114069455378395">"Cancelar"</string>
<string name="okay" msgid="949938843324579502">"Ok"</string>
+ <!-- no translation found for done (381184316122520313) -->
+ <skip />
<string name="alarms_and_reminders_label" msgid="6918395649731424294">"Alarmes e lembretes"</string>
<string name="alarms_and_reminders_switch_title" msgid="4939393911531826222">"Autorizar a definição de alarmes e lembretes"</string>
<string name="alarms_and_reminders_title" msgid="8819933264635406032">"Alarmes e lembretes"</string>
@@ -551,7 +553,9 @@
<string name="zen_mode_duration_always_prompt_title" msgid="3212996860498119555">"Perguntar sempre"</string>
<string name="zen_mode_forever" msgid="3339224497605461291">"Até você desativar"</string>
<string name="time_unit_just_now" msgid="3006134267292728099">"Agora"</string>
- <string name="media_transfer_this_device_name" msgid="2357329267148436433">"Este smartphone"</string>
+ <string name="media_transfer_this_device_name" product="default" msgid="2357329267148436433">"Este smartphone"</string>
+ <!-- no translation found for media_transfer_this_device_name (3714653244000242800) -->
+ <skip />
<string name="media_transfer_this_phone" msgid="7194341457812151531">"Este smartphone"</string>
<string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"Ocorreu um problema na conexão. Desligue o dispositivo e ligue-o novamente"</string>
<string name="media_transfer_wired_device_name" msgid="4447880899964056007">"Dispositivo de áudio com fio"</string>
@@ -591,7 +595,9 @@
<string name="user_set_lock_button" msgid="1427128184982594856">"Definir bloqueio"</string>
<string name="user_switch_to_user" msgid="6975428297154968543">"Mudar para <xliff:g id="USER_NAME">%s</xliff:g>"</string>
<string name="creating_new_user_dialog_message" msgid="7232880257538970375">"Criando novo usuário…"</string>
+ <string name="creating_new_guest_dialog_message" msgid="1114905602181350690">"Criando novo convidado…"</string>
<string name="add_user_failed" msgid="4809887794313944872">"Falha ao criar um novo usuário"</string>
+ <string name="add_guest_failed" msgid="8074548434469843443">"Falha ao criar um novo convidado"</string>
<string name="user_nickname" msgid="262624187455825083">"Apelido"</string>
<string name="guest_new_guest" msgid="3482026122932643557">"Adicionar convidado"</string>
<string name="guest_exit_guest" msgid="5908239569510734136">"Remover convidado"</string>
@@ -644,4 +650,7 @@
<string name="dream_complication_title_cast_info" msgid="4038776652841885084">"Info. de transmissão"</string>
<string name="avatar_picker_title" msgid="8492884172713170652">"Escolher a foto do perfil"</string>
<string name="default_user_icon_description" msgid="6554047177298972638">"Ícone de usuário padrão"</string>
+ <string name="physical_keyboard_title" msgid="4811935435315835220">"Teclado físico"</string>
+ <string name="keyboard_layout_dialog_title" msgid="3927180147005616290">"Escolha o layout do teclado"</string>
+ <string name="keyboard_layout_default_label" msgid="1997292217218546957">"Padrão"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-ro/strings.xml b/packages/SettingsLib/res/values-ro/strings.xml
index b110c9c..778351e 100644
--- a/packages/SettingsLib/res/values-ro/strings.xml
+++ b/packages/SettingsLib/res/values-ro/strings.xml
@@ -533,6 +533,8 @@
<string name="accessibility_manual_zen_less_time" msgid="6828877595848229965">"Mai puțin timp."</string>
<string name="cancel" msgid="5665114069455378395">"Anulați"</string>
<string name="okay" msgid="949938843324579502">"OK"</string>
+ <!-- no translation found for done (381184316122520313) -->
+ <skip />
<string name="alarms_and_reminders_label" msgid="6918395649731424294">"Alarme și mementouri"</string>
<string name="alarms_and_reminders_switch_title" msgid="4939393911531826222">"Permiteți setarea pentru alarme și mementouri"</string>
<string name="alarms_and_reminders_title" msgid="8819933264635406032">"Alarme și mementouri"</string>
@@ -551,7 +553,9 @@
<string name="zen_mode_duration_always_prompt_title" msgid="3212996860498119555">"Întreabă de fiecare dată"</string>
<string name="zen_mode_forever" msgid="3339224497605461291">"Până când dezactivați"</string>
<string name="time_unit_just_now" msgid="3006134267292728099">"Chiar acum"</string>
- <string name="media_transfer_this_device_name" msgid="2357329267148436433">"Acest telefon"</string>
+ <string name="media_transfer_this_device_name" product="default" msgid="2357329267148436433">"Acest telefon"</string>
+ <!-- no translation found for media_transfer_this_device_name (3714653244000242800) -->
+ <skip />
<string name="media_transfer_this_phone" msgid="7194341457812151531">"Acest telefon"</string>
<string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"Problemă la conectare. Opriți și reporniți dispozitivul."</string>
<string name="media_transfer_wired_device_name" msgid="4447880899964056007">"Dispozitiv audio cu fir"</string>
@@ -591,7 +595,9 @@
<string name="user_set_lock_button" msgid="1427128184982594856">"Configurați blocarea"</string>
<string name="user_switch_to_user" msgid="6975428297154968543">"Treceți la <xliff:g id="USER_NAME">%s</xliff:g>"</string>
<string name="creating_new_user_dialog_message" msgid="7232880257538970375">"Se creează un utilizator nou…"</string>
+ <string name="creating_new_guest_dialog_message" msgid="1114905602181350690">"Se creează un invitat nou…"</string>
<string name="add_user_failed" msgid="4809887794313944872">"Nu s-a creat noul utilizator"</string>
+ <string name="add_guest_failed" msgid="8074548434469843443">"Nu s-a putut crea un invitat nou"</string>
<string name="user_nickname" msgid="262624187455825083">"Pseudonim"</string>
<string name="guest_new_guest" msgid="3482026122932643557">"Adăugați un invitat"</string>
<string name="guest_exit_guest" msgid="5908239569510734136">"Ștergeți invitatul"</string>
@@ -644,4 +650,7 @@
<string name="dream_complication_title_cast_info" msgid="4038776652841885084">"Informații artiști"</string>
<string name="avatar_picker_title" msgid="8492884172713170652">"Alegeți o fotografie de profil"</string>
<string name="default_user_icon_description" msgid="6554047177298972638">"Pictograma prestabilită a utilizatorului"</string>
+ <string name="physical_keyboard_title" msgid="4811935435315835220">"Tastatură fizică"</string>
+ <string name="keyboard_layout_dialog_title" msgid="3927180147005616290">"Alegeți aspectul tastaturii"</string>
+ <string name="keyboard_layout_default_label" msgid="1997292217218546957">"Prestabilit"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-ru/strings.xml b/packages/SettingsLib/res/values-ru/strings.xml
index 6a2da7f..d07e12b 100644
--- a/packages/SettingsLib/res/values-ru/strings.xml
+++ b/packages/SettingsLib/res/values-ru/strings.xml
@@ -533,6 +533,8 @@
<string name="accessibility_manual_zen_less_time" msgid="6828877595848229965">"Уменьшить продолжительность"</string>
<string name="cancel" msgid="5665114069455378395">"Отмена"</string>
<string name="okay" msgid="949938843324579502">"ОК"</string>
+ <!-- no translation found for done (381184316122520313) -->
+ <skip />
<string name="alarms_and_reminders_label" msgid="6918395649731424294">"Будильники и напоминания"</string>
<string name="alarms_and_reminders_switch_title" msgid="4939393911531826222">"Разрешить установку будильников и напоминаний"</string>
<string name="alarms_and_reminders_title" msgid="8819933264635406032">"Будильники и напоминания"</string>
@@ -551,7 +553,9 @@
<string name="zen_mode_duration_always_prompt_title" msgid="3212996860498119555">"Всегда спрашивать"</string>
<string name="zen_mode_forever" msgid="3339224497605461291">"Пока вы не отключите"</string>
<string name="time_unit_just_now" msgid="3006134267292728099">"Только что"</string>
- <string name="media_transfer_this_device_name" msgid="2357329267148436433">"Этот смартфон"</string>
+ <string name="media_transfer_this_device_name" product="default" msgid="2357329267148436433">"Этот смартфон"</string>
+ <!-- no translation found for media_transfer_this_device_name (3714653244000242800) -->
+ <skip />
<string name="media_transfer_this_phone" msgid="7194341457812151531">"Этот смартфон"</string>
<string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"Ошибка подключения. Выключите и снова включите устройство."</string>
<string name="media_transfer_wired_device_name" msgid="4447880899964056007">"Проводное аудиоустройство"</string>
@@ -591,7 +595,9 @@
<string name="user_set_lock_button" msgid="1427128184982594856">"Включить блокировку"</string>
<string name="user_switch_to_user" msgid="6975428297154968543">"Сменить пользователя на <xliff:g id="USER_NAME">%s</xliff:g>"</string>
<string name="creating_new_user_dialog_message" msgid="7232880257538970375">"Создаем нового пользователя…"</string>
+ <string name="creating_new_guest_dialog_message" msgid="1114905602181350690">"Создание гостя…"</string>
<string name="add_user_failed" msgid="4809887794313944872">"Не удалось создать пользователя"</string>
+ <string name="add_guest_failed" msgid="8074548434469843443">"Не удалось создать гостя."</string>
<string name="user_nickname" msgid="262624187455825083">"Псевдоним"</string>
<string name="guest_new_guest" msgid="3482026122932643557">"Добавить гостя"</string>
<string name="guest_exit_guest" msgid="5908239569510734136">"Удалить аккаунт гостя"</string>
@@ -644,4 +650,7 @@
<string name="dream_complication_title_cast_info" msgid="4038776652841885084">"Данные о трансляции"</string>
<string name="avatar_picker_title" msgid="8492884172713170652">"Выберите фото профиля"</string>
<string name="default_user_icon_description" msgid="6554047177298972638">"Значок пользователя по умолчанию"</string>
+ <string name="physical_keyboard_title" msgid="4811935435315835220">"Физическая клавиатура"</string>
+ <string name="keyboard_layout_dialog_title" msgid="3927180147005616290">"Выберите раскладку клавиатуры"</string>
+ <string name="keyboard_layout_default_label" msgid="1997292217218546957">"По умолчанию"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-si/strings.xml b/packages/SettingsLib/res/values-si/strings.xml
index b75f548..5140e89 100644
--- a/packages/SettingsLib/res/values-si/strings.xml
+++ b/packages/SettingsLib/res/values-si/strings.xml
@@ -533,6 +533,8 @@
<string name="accessibility_manual_zen_less_time" msgid="6828877595848229965">"වේලාව අඩුවෙන්."</string>
<string name="cancel" msgid="5665114069455378395">"අවලංගු කරන්න"</string>
<string name="okay" msgid="949938843324579502">"හරි"</string>
+ <!-- no translation found for done (381184316122520313) -->
+ <skip />
<string name="alarms_and_reminders_label" msgid="6918395649731424294">"එලාම සහ සිහිකැඳවීම්"</string>
<string name="alarms_and_reminders_switch_title" msgid="4939393911531826222">"එලාම සහ සිහිකැඳවීම් සැකසීමට ඉඩ දෙන්න"</string>
<string name="alarms_and_reminders_title" msgid="8819933264635406032">"එලාම සහ සිහිකැඳවීම්"</string>
@@ -551,7 +553,9 @@
<string name="zen_mode_duration_always_prompt_title" msgid="3212996860498119555">"සෑම විටම ඉල්ලන්න"</string>
<string name="zen_mode_forever" msgid="3339224497605461291">"ඔබ ක්රියාවිරහිත කරන තුරු"</string>
<string name="time_unit_just_now" msgid="3006134267292728099">"මේ දැන්"</string>
- <string name="media_transfer_this_device_name" msgid="2357329267148436433">"මෙම දුරකථනය"</string>
+ <string name="media_transfer_this_device_name" product="default" msgid="2357329267148436433">"මෙම දුරකථනය"</string>
+ <!-- no translation found for media_transfer_this_device_name (3714653244000242800) -->
+ <skip />
<string name="media_transfer_this_phone" msgid="7194341457812151531">"මෙම දුරකථනය"</string>
<string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"සම්බන්ධ කිරීමේ ගැටලුවකි උපාංගය ක්රියාවිරහිත කර & ආපසු ක්රියාත්මක කරන්න"</string>
<string name="media_transfer_wired_device_name" msgid="4447880899964056007">"රැහැන්ගත කළ ඕඩියෝ උපාංගය"</string>
@@ -591,7 +595,9 @@
<string name="user_set_lock_button" msgid="1427128184982594856">"අගුල සකසන්න"</string>
<string name="user_switch_to_user" msgid="6975428297154968543">"<xliff:g id="USER_NAME">%s</xliff:g> වෙත මාරු වන්න"</string>
<string name="creating_new_user_dialog_message" msgid="7232880257538970375">"නව පරිශීලක තනමින්…"</string>
+ <string name="creating_new_guest_dialog_message" msgid="1114905602181350690">"නව අමුත්තකු තනමින්…"</string>
<string name="add_user_failed" msgid="4809887794313944872">"නව පරිශීලකයෙකු තැනීමට අසමත් විය"</string>
+ <string name="add_guest_failed" msgid="8074548434469843443">"නව අමුත්තකු තැනීම අසාර්ථක විය"</string>
<string name="user_nickname" msgid="262624187455825083">"අපනාමය"</string>
<string name="guest_new_guest" msgid="3482026122932643557">"අමුත්තා එක් කරන්න"</string>
<string name="guest_exit_guest" msgid="5908239569510734136">"අමුත්තා ඉවත් කරන්න"</string>
@@ -644,4 +650,7 @@
<string name="dream_complication_title_cast_info" msgid="4038776652841885084">"විකාශ තතු"</string>
<string name="avatar_picker_title" msgid="8492884172713170652">"පැතිකඩ පින්තූරයක් තේරීම"</string>
<string name="default_user_icon_description" msgid="6554047177298972638">"පෙරනිමි පරිශීලක නිරූපකය"</string>
+ <string name="physical_keyboard_title" msgid="4811935435315835220">"භෞතික යතුරු පුවරුව"</string>
+ <string name="keyboard_layout_dialog_title" msgid="3927180147005616290">"යතුරු පුවරු පිරිසැලසුම තෝරන්න"</string>
+ <string name="keyboard_layout_default_label" msgid="1997292217218546957">"පෙරනිමි"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-sk/strings.xml b/packages/SettingsLib/res/values-sk/strings.xml
index 83f880d..b53a799 100644
--- a/packages/SettingsLib/res/values-sk/strings.xml
+++ b/packages/SettingsLib/res/values-sk/strings.xml
@@ -533,6 +533,8 @@
<string name="accessibility_manual_zen_less_time" msgid="6828877595848229965">"Kratší čas."</string>
<string name="cancel" msgid="5665114069455378395">"Zrušiť"</string>
<string name="okay" msgid="949938843324579502">"OK"</string>
+ <!-- no translation found for done (381184316122520313) -->
+ <skip />
<string name="alarms_and_reminders_label" msgid="6918395649731424294">"Budíky a pripomenutia"</string>
<string name="alarms_and_reminders_switch_title" msgid="4939393911531826222">"Povoliť nastavovanie budíkov a pripomenutí"</string>
<string name="alarms_and_reminders_title" msgid="8819933264635406032">"Budíky a pripomenutia"</string>
@@ -551,7 +553,9 @@
<string name="zen_mode_duration_always_prompt_title" msgid="3212996860498119555">"Vždy sa opýtať"</string>
<string name="zen_mode_forever" msgid="3339224497605461291">"Dokým funkciu nevypnete"</string>
<string name="time_unit_just_now" msgid="3006134267292728099">"Teraz"</string>
- <string name="media_transfer_this_device_name" msgid="2357329267148436433">"Tento telefón"</string>
+ <string name="media_transfer_this_device_name" product="default" msgid="2357329267148436433">"Tento telefón"</string>
+ <!-- no translation found for media_transfer_this_device_name (3714653244000242800) -->
+ <skip />
<string name="media_transfer_this_phone" msgid="7194341457812151531">"Tento telefón"</string>
<string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"Pri pripájaní sa vyskytol problém. Zariadenie vypnite a znova zapnite."</string>
<string name="media_transfer_wired_device_name" msgid="4447880899964056007">"Audio zariadenie s káblom"</string>
@@ -591,7 +595,9 @@
<string name="user_set_lock_button" msgid="1427128184982594856">"Nastaviť uzamknutie"</string>
<string name="user_switch_to_user" msgid="6975428297154968543">"Prepnúť na používateľa <xliff:g id="USER_NAME">%s</xliff:g>"</string>
<string name="creating_new_user_dialog_message" msgid="7232880257538970375">"Vytvára sa nový používateľ…"</string>
+ <string name="creating_new_guest_dialog_message" msgid="1114905602181350690">"Vytvára sa nový hosť…"</string>
<string name="add_user_failed" msgid="4809887794313944872">"Nového použív. sa nepodarilo vytvoriť"</string>
+ <string name="add_guest_failed" msgid="8074548434469843443">"Nového hosťa sa nepodarilo vytvoriť"</string>
<string name="user_nickname" msgid="262624187455825083">"Prezývka"</string>
<string name="guest_new_guest" msgid="3482026122932643557">"Pridať hosťa"</string>
<string name="guest_exit_guest" msgid="5908239569510734136">"Odobrať hosťa"</string>
@@ -644,4 +650,7 @@
<string name="dream_complication_title_cast_info" msgid="4038776652841885084">"Informácie o prenose"</string>
<string name="avatar_picker_title" msgid="8492884172713170652">"Výber profilovej fotky"</string>
<string name="default_user_icon_description" msgid="6554047177298972638">"Predvolená ikona používateľa"</string>
+ <string name="physical_keyboard_title" msgid="4811935435315835220">"Fyzická klávesnica"</string>
+ <string name="keyboard_layout_dialog_title" msgid="3927180147005616290">"Vyberte rozloženie klávesnice"</string>
+ <string name="keyboard_layout_default_label" msgid="1997292217218546957">"Predvolené"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-sl/strings.xml b/packages/SettingsLib/res/values-sl/strings.xml
index 6d4078d..67e20b1 100644
--- a/packages/SettingsLib/res/values-sl/strings.xml
+++ b/packages/SettingsLib/res/values-sl/strings.xml
@@ -533,6 +533,8 @@
<string name="accessibility_manual_zen_less_time" msgid="6828877595848229965">"Krajši čas."</string>
<string name="cancel" msgid="5665114069455378395">"Prekliči"</string>
<string name="okay" msgid="949938843324579502">"V redu"</string>
+ <!-- no translation found for done (381184316122520313) -->
+ <skip />
<string name="alarms_and_reminders_label" msgid="6918395649731424294">"Alarmi in opomniki"</string>
<string name="alarms_and_reminders_switch_title" msgid="4939393911531826222">"Dovoli nastavljanje alarmov in opomnikov"</string>
<string name="alarms_and_reminders_title" msgid="8819933264635406032">"Alarmi in opomniki"</string>
@@ -551,7 +553,9 @@
<string name="zen_mode_duration_always_prompt_title" msgid="3212996860498119555">"Vedno vprašaj"</string>
<string name="zen_mode_forever" msgid="3339224497605461291">"Dokler ne izklopite"</string>
<string name="time_unit_just_now" msgid="3006134267292728099">"Pravkar"</string>
- <string name="media_transfer_this_device_name" msgid="2357329267148436433">"Ta telefon"</string>
+ <string name="media_transfer_this_device_name" product="default" msgid="2357329267148436433">"Ta telefon"</string>
+ <!-- no translation found for media_transfer_this_device_name (3714653244000242800) -->
+ <skip />
<string name="media_transfer_this_phone" msgid="7194341457812151531">"Ta telefon"</string>
<string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"Težava pri povezovanju. Napravo izklopite in znova vklopite."</string>
<string name="media_transfer_wired_device_name" msgid="4447880899964056007">"Žična zvočna naprava"</string>
@@ -591,7 +595,9 @@
<string name="user_set_lock_button" msgid="1427128184982594856">"Nastavi zaklepanje"</string>
<string name="user_switch_to_user" msgid="6975428297154968543">"Preklopi na račun <xliff:g id="USER_NAME">%s</xliff:g>"</string>
<string name="creating_new_user_dialog_message" msgid="7232880257538970375">"Ustvarjanje novega uporabnika …"</string>
+ <string name="creating_new_guest_dialog_message" msgid="1114905602181350690">"Ustvarjanje novega gosta …"</string>
<string name="add_user_failed" msgid="4809887794313944872">"Ustvarjanje novega uporabnika ni uspelo."</string>
+ <string name="add_guest_failed" msgid="8074548434469843443">"Ustvarjanje novega gosta ni uspelo."</string>
<string name="user_nickname" msgid="262624187455825083">"Vzdevek"</string>
<string name="guest_new_guest" msgid="3482026122932643557">"Dodajanje gosta"</string>
<string name="guest_exit_guest" msgid="5908239569510734136">"Odstranitev gosta"</string>
@@ -644,4 +650,7 @@
<string name="dream_complication_title_cast_info" msgid="4038776652841885084">"O zasedbi"</string>
<string name="avatar_picker_title" msgid="8492884172713170652">"Izbira profilne slike"</string>
<string name="default_user_icon_description" msgid="6554047177298972638">"Privzeta ikona uporabnika"</string>
+ <string name="physical_keyboard_title" msgid="4811935435315835220">"Fizična tipkovnica"</string>
+ <string name="keyboard_layout_dialog_title" msgid="3927180147005616290">"Izbira razporeditve tipkovnice"</string>
+ <string name="keyboard_layout_default_label" msgid="1997292217218546957">"Privzeto"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-sq/strings.xml b/packages/SettingsLib/res/values-sq/strings.xml
index ef1e59d..fc2639e 100644
--- a/packages/SettingsLib/res/values-sq/strings.xml
+++ b/packages/SettingsLib/res/values-sq/strings.xml
@@ -533,6 +533,8 @@
<string name="accessibility_manual_zen_less_time" msgid="6828877595848229965">"Më pak kohë."</string>
<string name="cancel" msgid="5665114069455378395">"Anulo"</string>
<string name="okay" msgid="949938843324579502">"Në rregull"</string>
+ <!-- no translation found for done (381184316122520313) -->
+ <skip />
<string name="alarms_and_reminders_label" msgid="6918395649731424294">"Alarmet dhe alarmet rikujtuese"</string>
<string name="alarms_and_reminders_switch_title" msgid="4939393911531826222">"Lejo caktimin e alarmeve dhe alarmeve rikujtuese"</string>
<string name="alarms_and_reminders_title" msgid="8819933264635406032">"Alarmet dhe alarmet rikujtuese"</string>
@@ -551,7 +553,9 @@
<string name="zen_mode_duration_always_prompt_title" msgid="3212996860498119555">"Pyet çdo herë"</string>
<string name="zen_mode_forever" msgid="3339224497605461291">"Derisa ta çaktivizosh"</string>
<string name="time_unit_just_now" msgid="3006134267292728099">"Pikërisht tani"</string>
- <string name="media_transfer_this_device_name" msgid="2357329267148436433">"Ky telefon"</string>
+ <string name="media_transfer_this_device_name" product="default" msgid="2357329267148436433">"Ky telefon"</string>
+ <!-- no translation found for media_transfer_this_device_name (3714653244000242800) -->
+ <skip />
<string name="media_transfer_this_phone" msgid="7194341457812151531">"Ky telefon"</string>
<string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"Problem me lidhjen. Fike dhe ndize përsëri pajisjen"</string>
<string name="media_transfer_wired_device_name" msgid="4447880899964056007">"Pajisja audio me tel"</string>
@@ -591,7 +595,9 @@
<string name="user_set_lock_button" msgid="1427128184982594856">"Cakto kyçjen"</string>
<string name="user_switch_to_user" msgid="6975428297154968543">"Kalo te <xliff:g id="USER_NAME">%s</xliff:g>"</string>
<string name="creating_new_user_dialog_message" msgid="7232880257538970375">"Po krijohet një përdorues i ri…"</string>
+ <string name="creating_new_guest_dialog_message" msgid="1114905602181350690">"Po krijohet një vizitor i ri…"</string>
<string name="add_user_failed" msgid="4809887794313944872">"Krijimi i një përdoruesi të ri dështoi"</string>
+ <string name="add_guest_failed" msgid="8074548434469843443">"Profili i vizitorit të ri nuk u krijua"</string>
<string name="user_nickname" msgid="262624187455825083">"Pseudonimi"</string>
<string name="guest_new_guest" msgid="3482026122932643557">"Shto të ftuar"</string>
<string name="guest_exit_guest" msgid="5908239569510734136">"Hiq të ftuarin"</string>
@@ -644,4 +650,7 @@
<string name="dream_complication_title_cast_info" msgid="4038776652841885084">"Të dhënat e aktorëve"</string>
<string name="avatar_picker_title" msgid="8492884172713170652">"Zgjidh një fotografi profili"</string>
<string name="default_user_icon_description" msgid="6554047177298972638">"Ikona e parazgjedhur e përdoruesit"</string>
+ <string name="physical_keyboard_title" msgid="4811935435315835220">"Tastiera fizike"</string>
+ <string name="keyboard_layout_dialog_title" msgid="3927180147005616290">"Zgjidh strukturën e tastierës"</string>
+ <string name="keyboard_layout_default_label" msgid="1997292217218546957">"Parazgjedhja"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-sr/strings.xml b/packages/SettingsLib/res/values-sr/strings.xml
index 333720e..44080fa 100644
--- a/packages/SettingsLib/res/values-sr/strings.xml
+++ b/packages/SettingsLib/res/values-sr/strings.xml
@@ -533,6 +533,8 @@
<string name="accessibility_manual_zen_less_time" msgid="6828877595848229965">"Мање времена."</string>
<string name="cancel" msgid="5665114069455378395">"Откажи"</string>
<string name="okay" msgid="949938843324579502">"Потврди"</string>
+ <!-- no translation found for done (381184316122520313) -->
+ <skip />
<string name="alarms_and_reminders_label" msgid="6918395649731424294">"Аларми и подсетници"</string>
<string name="alarms_and_reminders_switch_title" msgid="4939393911531826222">"Омогући подешавање аларма и подсетника"</string>
<string name="alarms_and_reminders_title" msgid="8819933264635406032">"Аларми и подсетници"</string>
@@ -551,7 +553,9 @@
<string name="zen_mode_duration_always_prompt_title" msgid="3212996860498119555">"Питај сваки пут"</string>
<string name="zen_mode_forever" msgid="3339224497605461291">"Док не искључите"</string>
<string name="time_unit_just_now" msgid="3006134267292728099">"Управо"</string>
- <string name="media_transfer_this_device_name" msgid="2357329267148436433">"Овај телефон"</string>
+ <string name="media_transfer_this_device_name" product="default" msgid="2357329267148436433">"Овај телефон"</string>
+ <!-- no translation found for media_transfer_this_device_name (3714653244000242800) -->
+ <skip />
<string name="media_transfer_this_phone" msgid="7194341457812151531">"Овај телефон"</string>
<string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"Проблем при повезивању. Искључите уређај, па га поново укључите"</string>
<string name="media_transfer_wired_device_name" msgid="4447880899964056007">"Жичани аудио уређај"</string>
@@ -591,7 +595,9 @@
<string name="user_set_lock_button" msgid="1427128184982594856">"Подеси закључавање"</string>
<string name="user_switch_to_user" msgid="6975428297154968543">"Пређи на корисника <xliff:g id="USER_NAME">%s</xliff:g>"</string>
<string name="creating_new_user_dialog_message" msgid="7232880257538970375">"Прави се нови корисник…"</string>
+ <string name="creating_new_guest_dialog_message" msgid="1114905602181350690">"Прави се нови гост…"</string>
<string name="add_user_failed" msgid="4809887794313944872">"Прављење новог корисника није успело"</string>
+ <string name="add_guest_failed" msgid="8074548434469843443">"Прављење новог госта није успело"</string>
<string name="user_nickname" msgid="262624187455825083">"Надимак"</string>
<string name="guest_new_guest" msgid="3482026122932643557">"Додај госта"</string>
<string name="guest_exit_guest" msgid="5908239569510734136">"Уклони госта"</string>
@@ -644,4 +650,7 @@
<string name="dream_complication_title_cast_info" msgid="4038776652841885084">"Подаци о пребацивању"</string>
<string name="avatar_picker_title" msgid="8492884172713170652">"Одаберите слику профила"</string>
<string name="default_user_icon_description" msgid="6554047177298972638">"Подразумевана икона корисника"</string>
+ <string name="physical_keyboard_title" msgid="4811935435315835220">"Физичка тастатура"</string>
+ <string name="keyboard_layout_dialog_title" msgid="3927180147005616290">"Одаберите распоред тастатуре"</string>
+ <string name="keyboard_layout_default_label" msgid="1997292217218546957">"Подразумевано"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-sv/strings.xml b/packages/SettingsLib/res/values-sv/strings.xml
index 2522d7d..fbcc2ba 100644
--- a/packages/SettingsLib/res/values-sv/strings.xml
+++ b/packages/SettingsLib/res/values-sv/strings.xml
@@ -533,6 +533,8 @@
<string name="accessibility_manual_zen_less_time" msgid="6828877595848229965">"Kortare tid."</string>
<string name="cancel" msgid="5665114069455378395">"Avbryt"</string>
<string name="okay" msgid="949938843324579502">"OK"</string>
+ <!-- no translation found for done (381184316122520313) -->
+ <skip />
<string name="alarms_and_reminders_label" msgid="6918395649731424294">"Alarm och påminnelser"</string>
<string name="alarms_and_reminders_switch_title" msgid="4939393911531826222">"Tillåt att alarm och påminnelser ställs in"</string>
<string name="alarms_and_reminders_title" msgid="8819933264635406032">"Alarm och påminnelser"</string>
@@ -551,7 +553,9 @@
<string name="zen_mode_duration_always_prompt_title" msgid="3212996860498119555">"Fråga varje gång"</string>
<string name="zen_mode_forever" msgid="3339224497605461291">"Tills du inaktiverar funktionen"</string>
<string name="time_unit_just_now" msgid="3006134267292728099">"Nyss"</string>
- <string name="media_transfer_this_device_name" msgid="2357329267148436433">"Den här telefonen"</string>
+ <string name="media_transfer_this_device_name" product="default" msgid="2357329267148436433">"Den här telefonen"</string>
+ <!-- no translation found for media_transfer_this_device_name (3714653244000242800) -->
+ <skip />
<string name="media_transfer_this_phone" msgid="7194341457812151531">"Den här telefonen"</string>
<string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"Det gick inte att ansluta. Stäng av enheten och slå på den igen"</string>
<string name="media_transfer_wired_device_name" msgid="4447880899964056007">"Ljudenhet med kabelanslutning"</string>
@@ -591,7 +595,9 @@
<string name="user_set_lock_button" msgid="1427128184982594856">"Konfigurera lås"</string>
<string name="user_switch_to_user" msgid="6975428297154968543">"Byt till <xliff:g id="USER_NAME">%s</xliff:g>"</string>
<string name="creating_new_user_dialog_message" msgid="7232880257538970375">"Skapar ny användare …"</string>
+ <string name="creating_new_guest_dialog_message" msgid="1114905602181350690">"Skapar ny gäst …"</string>
<string name="add_user_failed" msgid="4809887794313944872">"Det gick inte att skapa en ny användare"</string>
+ <string name="add_guest_failed" msgid="8074548434469843443">"Det gick inte att skapa en ny gäst"</string>
<string name="user_nickname" msgid="262624187455825083">"Smeknamn"</string>
<string name="guest_new_guest" msgid="3482026122932643557">"Lägg till gäst"</string>
<string name="guest_exit_guest" msgid="5908239569510734136">"Ta bort gäst"</string>
@@ -644,4 +650,10 @@
<string name="dream_complication_title_cast_info" msgid="4038776652841885084">"Info om rollistan"</string>
<string name="avatar_picker_title" msgid="8492884172713170652">"Välj en profilbild"</string>
<string name="default_user_icon_description" msgid="6554047177298972638">"Ikon för standardanvändare"</string>
+ <!-- no translation found for physical_keyboard_title (4811935435315835220) -->
+ <skip />
+ <!-- no translation found for keyboard_layout_dialog_title (3927180147005616290) -->
+ <skip />
+ <!-- no translation found for keyboard_layout_default_label (1997292217218546957) -->
+ <skip />
</resources>
diff --git a/packages/SettingsLib/res/values-sw/strings.xml b/packages/SettingsLib/res/values-sw/strings.xml
index d6deb2b..8000841 100644
--- a/packages/SettingsLib/res/values-sw/strings.xml
+++ b/packages/SettingsLib/res/values-sw/strings.xml
@@ -533,6 +533,8 @@
<string name="accessibility_manual_zen_less_time" msgid="6828877595848229965">"Muda kidogo."</string>
<string name="cancel" msgid="5665114069455378395">"Ghairi"</string>
<string name="okay" msgid="949938843324579502">"Sawa"</string>
+ <!-- no translation found for done (381184316122520313) -->
+ <skip />
<string name="alarms_and_reminders_label" msgid="6918395649731424294">"Ving\'ora na vikumbusho"</string>
<string name="alarms_and_reminders_switch_title" msgid="4939393911531826222">"Ruhusu iweke kengele na vikumbusho"</string>
<string name="alarms_and_reminders_title" msgid="8819933264635406032">"Kengele na vikumbusho"</string>
@@ -551,7 +553,9 @@
<string name="zen_mode_duration_always_prompt_title" msgid="3212996860498119555">"Uliza kila wakati"</string>
<string name="zen_mode_forever" msgid="3339224497605461291">"Hadi utakapoizima"</string>
<string name="time_unit_just_now" msgid="3006134267292728099">"Sasa hivi"</string>
- <string name="media_transfer_this_device_name" msgid="2357329267148436433">"Simu hii"</string>
+ <string name="media_transfer_this_device_name" product="default" msgid="2357329267148436433">"Simu hii"</string>
+ <!-- no translation found for media_transfer_this_device_name (3714653244000242800) -->
+ <skip />
<string name="media_transfer_this_phone" msgid="7194341457812151531">"Simu hii"</string>
<string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"Kuna tatizo la kuunganisha kwenye Intaneti. Zima kisha uwashe kifaa"</string>
<string name="media_transfer_wired_device_name" msgid="4447880899964056007">"Kifaa cha sauti kinachotumia waya"</string>
@@ -591,7 +595,9 @@
<string name="user_set_lock_button" msgid="1427128184982594856">"Weka ufunguo"</string>
<string name="user_switch_to_user" msgid="6975428297154968543">"Badili utumie <xliff:g id="USER_NAME">%s</xliff:g>"</string>
<string name="creating_new_user_dialog_message" msgid="7232880257538970375">"Inaweka mtumiaji mpya…"</string>
+ <string name="creating_new_guest_dialog_message" msgid="1114905602181350690">"Inaunda wasifu mpya wa mgeni…"</string>
<string name="add_user_failed" msgid="4809887794313944872">"Imeshindwa kuweka mtumiaji mpya"</string>
+ <string name="add_guest_failed" msgid="8074548434469843443">"Imeshindwa kuunda wasifu mpya wa mgeni"</string>
<string name="user_nickname" msgid="262624187455825083">"Jina wakilishi"</string>
<string name="guest_new_guest" msgid="3482026122932643557">"Ongeza mgeni"</string>
<string name="guest_exit_guest" msgid="5908239569510734136">"Ondoa mgeni"</string>
@@ -644,4 +650,7 @@
<string name="dream_complication_title_cast_info" msgid="4038776652841885084">"Maelezo ya Wahusika"</string>
<string name="avatar_picker_title" msgid="8492884172713170652">"Chagua picha ya wasifu"</string>
<string name="default_user_icon_description" msgid="6554047177298972638">"Aikoni chaguomsingi ya mtumiaji"</string>
+ <string name="physical_keyboard_title" msgid="4811935435315835220">"Kibodi halisi"</string>
+ <string name="keyboard_layout_dialog_title" msgid="3927180147005616290">"Chagua mpangilio wa kibodi"</string>
+ <string name="keyboard_layout_default_label" msgid="1997292217218546957">"Chaguomsingi"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-ta/strings.xml b/packages/SettingsLib/res/values-ta/strings.xml
index 8d5b876..30da814 100644
--- a/packages/SettingsLib/res/values-ta/strings.xml
+++ b/packages/SettingsLib/res/values-ta/strings.xml
@@ -533,6 +533,8 @@
<string name="accessibility_manual_zen_less_time" msgid="6828877595848229965">"நேரத்தைக் குறைக்கும்."</string>
<string name="cancel" msgid="5665114069455378395">"ரத்துசெய்"</string>
<string name="okay" msgid="949938843324579502">"சரி"</string>
+ <!-- no translation found for done (381184316122520313) -->
+ <skip />
<string name="alarms_and_reminders_label" msgid="6918395649731424294">"அலாரங்களும் நினைவூட்டல்களும்"</string>
<string name="alarms_and_reminders_switch_title" msgid="4939393911531826222">"அலாரங்கள் & நினைவூட்டல்களை அமைக்க அனுமதித்தல்"</string>
<string name="alarms_and_reminders_title" msgid="8819933264635406032">"அலாரங்கள் & நினைவூட்டல்கள்"</string>
@@ -551,7 +553,9 @@
<string name="zen_mode_duration_always_prompt_title" msgid="3212996860498119555">"ஒவ்வொரு முறையும் கேள்"</string>
<string name="zen_mode_forever" msgid="3339224497605461291">"ஆஃப் செய்யும் வரை"</string>
<string name="time_unit_just_now" msgid="3006134267292728099">"சற்றுமுன்"</string>
- <string name="media_transfer_this_device_name" msgid="2357329267148436433">"இந்த மொபைல்"</string>
+ <string name="media_transfer_this_device_name" product="default" msgid="2357329267148436433">"இந்த மொபைல்"</string>
+ <!-- no translation found for media_transfer_this_device_name (3714653244000242800) -->
+ <skip />
<string name="media_transfer_this_phone" msgid="7194341457812151531">"இந்த மொபைல்"</string>
<string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"இணைப்பதில் சிக்கல். சாதனத்தை ஆஃப் செய்து மீண்டும் ஆன் செய்யவும்"</string>
<string name="media_transfer_wired_device_name" msgid="4447880899964056007">"வயருடன்கூடிய ஆடியோ சாதனம்"</string>
@@ -591,7 +595,9 @@
<string name="user_set_lock_button" msgid="1427128184982594856">"பூட்டை அமை"</string>
<string name="user_switch_to_user" msgid="6975428297154968543">"<xliff:g id="USER_NAME">%s</xliff:g>க்கு மாறு"</string>
<string name="creating_new_user_dialog_message" msgid="7232880257538970375">"புதிய பயனரை உருவாக்குகிறது…"</string>
+ <string name="creating_new_guest_dialog_message" msgid="1114905602181350690">"புதிய விருந்தினரை உருவாக்குகிறது…"</string>
<string name="add_user_failed" msgid="4809887794313944872">"புதிய பயனரை உருவாக்க முடியவில்லை"</string>
+ <string name="add_guest_failed" msgid="8074548434469843443">"புதிய விருந்தினரை உருவாக்க முடியவில்லை"</string>
<string name="user_nickname" msgid="262624187455825083">"புனைப்பெயர்"</string>
<string name="guest_new_guest" msgid="3482026122932643557">"கெஸ்ட்டைச் சேர்"</string>
<string name="guest_exit_guest" msgid="5908239569510734136">"கெஸ்ட்டை அகற்று"</string>
@@ -644,4 +650,7 @@
<string name="dream_complication_title_cast_info" msgid="4038776652841885084">"அலைபரப்புத் தகவல்"</string>
<string name="avatar_picker_title" msgid="8492884172713170652">"சுயவிவரப் படத்தைத் தேர்வுசெய்யுங்கள்"</string>
<string name="default_user_icon_description" msgid="6554047177298972638">"இயல்புநிலைப் பயனர் ஐகான்"</string>
+ <string name="physical_keyboard_title" msgid="4811935435315835220">"கீபோர்டு"</string>
+ <string name="keyboard_layout_dialog_title" msgid="3927180147005616290">"கீபோர்டு தளவமைப்பைத் தேர்வுசெய்தல்"</string>
+ <string name="keyboard_layout_default_label" msgid="1997292217218546957">"இயல்பு"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-te/strings.xml b/packages/SettingsLib/res/values-te/strings.xml
index 1744832..34a324e 100644
--- a/packages/SettingsLib/res/values-te/strings.xml
+++ b/packages/SettingsLib/res/values-te/strings.xml
@@ -442,11 +442,11 @@
<string name="select_webview_provider_title" msgid="3917815648099445503">"వెబ్ వీక్షణ అమలు"</string>
<string name="select_webview_provider_dialog_title" msgid="2444261109877277714">"వెబ్ వీక్షణ అమలుని సెట్ చేయండి"</string>
<string name="select_webview_provider_toast_text" msgid="8512254949169359848">"ఈ ఎంపిక ఇప్పుడు లేదు. మళ్లీ ప్రయత్నించండి."</string>
- <string name="convert_to_file_encryption" msgid="2828976934129751818">"ఫైల్ గుప్తీకరణకు మార్చు"</string>
+ <string name="convert_to_file_encryption" msgid="2828976934129751818">"ఫైల్ ఎన్క్రిప్షన్కు మార్చు"</string>
<string name="convert_to_file_encryption_enabled" msgid="840757431284311754">"మార్చండి…"</string>
- <string name="convert_to_file_encryption_done" msgid="8965831011811180627">"ఫైల్ ఇప్పటికే గుప్తీకరించబడింది"</string>
- <string name="title_convert_fbe" msgid="5780013350366495149">"ఫైల్ ఆధారిత గుప్తీకరణకు మార్చడం"</string>
- <string name="convert_to_fbe_warning" msgid="34294381569282109">"డేటా భాగాన్ని ఫైల్ ఆధారిత గుప్తీకరణకు మార్చండి.\n !!హెచ్చరిక!! దీని వలన మీ డేటా మొత్తం తీసివేయబడుతుంది.\n ఈ లక్షణం ఆల్ఫా, కనుక సరిగ్గా పని చేయకపోవచ్చు.\n కొనసాగించడానికి \'తొలగించి, మార్చు...\' నొక్కండి."</string>
+ <string name="convert_to_file_encryption_done" msgid="8965831011811180627">"ఫైల్ ఇప్పటికే ఎన్క్రిప్ట్ చేయబడింది"</string>
+ <string name="title_convert_fbe" msgid="5780013350366495149">"ఫైల్ ఆధారిత ఎన్క్రిప్షన్కు మార్చడం"</string>
+ <string name="convert_to_fbe_warning" msgid="34294381569282109">"డేటా భాగాన్ని ఫైల్ ఆధారిత ఎన్క్రిప్షన్కు మార్చండి.\n !!హెచ్చరిక!! దీని వలన మీ డేటా మొత్తం తీసివేయబడుతుంది.\n ఈ లక్షణం ఆల్ఫా, కనుక సరిగ్గా పని చేయకపోవచ్చు.\n కొనసాగించడానికి \'తొలగించి, మార్చు...\' నొక్కండి."</string>
<string name="button_convert_fbe" msgid="1159861795137727671">"తొలగించి, మార్చు…"</string>
<string name="picture_color_mode" msgid="1013807330552931903">"చిత్రం రంగు మోడ్"</string>
<string name="picture_color_mode_desc" msgid="151780973768136200">"sRGB ఉపయోగిస్తుంది"</string>
@@ -533,6 +533,8 @@
<string name="accessibility_manual_zen_less_time" msgid="6828877595848229965">"తక్కువ సమయం."</string>
<string name="cancel" msgid="5665114069455378395">"రద్దు చేయి"</string>
<string name="okay" msgid="949938843324579502">"సరే"</string>
+ <!-- no translation found for done (381184316122520313) -->
+ <skip />
<string name="alarms_and_reminders_label" msgid="6918395649731424294">"అలారాలు, రిమైండర్లు"</string>
<string name="alarms_and_reminders_switch_title" msgid="4939393911531826222">"అలారాలు, రిమైండర్లను సెట్ చేయడానికి అనుమతించండి"</string>
<string name="alarms_and_reminders_title" msgid="8819933264635406032">"అలారాలు & రిమైండర్లు"</string>
@@ -551,7 +553,9 @@
<string name="zen_mode_duration_always_prompt_title" msgid="3212996860498119555">"ప్రతిసారి అడుగు"</string>
<string name="zen_mode_forever" msgid="3339224497605461291">"మీరు ఆఫ్ చేసే వరకు"</string>
<string name="time_unit_just_now" msgid="3006134267292728099">"ఇప్పుడే"</string>
- <string name="media_transfer_this_device_name" msgid="2357329267148436433">"ఈ ఫోన్"</string>
+ <string name="media_transfer_this_device_name" product="default" msgid="2357329267148436433">"ఈ ఫోన్"</string>
+ <!-- no translation found for media_transfer_this_device_name (3714653244000242800) -->
+ <skip />
<string name="media_transfer_this_phone" msgid="7194341457812151531">"ఈ ఫోన్"</string>
<string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"కనెక్ట్ చేయడంలో సమస్య ఉంది. పరికరాన్ని ఆఫ్ చేసి, ఆపై తిరిగి ఆన్ చేయండి"</string>
<string name="media_transfer_wired_device_name" msgid="4447880899964056007">"వైర్ గల ఆడియో పరికరం"</string>
@@ -575,7 +579,7 @@
<string name="user_add_user_item_title" msgid="2394272381086965029">"యూజర్"</string>
<string name="user_add_profile_item_title" msgid="3111051717414643029">"పరిమితం చేయబడిన ప్రొఫైల్"</string>
<string name="user_add_user_title" msgid="5457079143694924885">"కొత్త వినియోగదారుని జోడించాలా?"</string>
- <string name="user_add_user_message_long" msgid="1527434966294733380">"అదనపు యూజర్లను సృష్టించడం ద్వారా మీరు ఈ దేవైజ్ను ఇతరులతో షేర్ చేయవచ్చు. ప్రతి యూజర్కు వారికంటూ ప్రత్యేక స్థలం ఉంటుంది, వారు ఆ స్థలాన్ని యాప్లు, వాల్పేపర్ మొదలైనవాటితో అనుకూలీకరించవచ్చు. యూజర్లు ప్రతి ఒక్కరిపై ప్రభావం చూపే Wi‑Fi వంటి పరికర సెట్టింగ్లను కూడా సర్దుబాటు చేయవచ్చు.\n\nమీరు కొత్త యూజర్ ను జోడించినప్పుడు, ఆ వ్యక్తి వారికంటూ స్వంత స్థలం సెట్ చేసుకోవాలి.\n\nఏ వినియోగదారు అయినా మిగిలిన అందరు యూజర్ల కోసం యాప్లను అప్డేట్ చేయవచ్చు. యాక్సెస్ సామర్ధ్యం సెట్టింగ్లు మరియు సేవలు కొత్త యూజర్కి బదిలీ కాకపోవచ్చు."</string>
+ <string name="user_add_user_message_long" msgid="1527434966294733380">"అదనపు యూజర్లను క్రియేట్ చేయడం ద్వారా మీరు ఈ దేవైజ్ను ఇతరులతో షేర్ చేయవచ్చు. ప్రతి యూజర్కు వారికంటూ ప్రత్యేక స్థలం ఉంటుంది, వారు ఆ స్థలాన్ని యాప్లు, వాల్పేపర్ మొదలైనవాటితో అనుకూలీకరించవచ్చు. యూజర్లు ప్రతి ఒక్కరిపై ప్రభావం చూపే Wi‑Fi వంటి పరికర సెట్టింగ్లను కూడా సర్దుబాటు చేయవచ్చు.\n\nమీరు కొత్త యూజర్ ను జోడించినప్పుడు, ఆ వ్యక్తి వారికంటూ స్వంత స్థలం సెట్ చేసుకోవాలి.\n\nఏ వినియోగదారు అయినా మిగిలిన అందరు యూజర్ల కోసం యాప్లను అప్డేట్ చేయవచ్చు. యాక్సెస్ సామర్ధ్యం సెట్టింగ్లు మరియు సేవలు కొత్త యూజర్కి బదిలీ కాకపోవచ్చు."</string>
<string name="user_add_user_message_short" msgid="3295959985795716166">"మీరు కొత్త వినియోగదారుని జోడించినప్పుడు, ఆ వ్యక్తి తన స్థలాన్ని సెటప్ చేసుకోవాలి.\n\nఏ వినియోగదారు అయినా మిగతా అందరు వినియోగదారుల కోసం యాప్లను అప్డేట్ చేయగలరు."</string>
<string name="user_setup_dialog_title" msgid="8037342066381939995">"యూజర్ను ఇప్పుడే సెటప్ చేయాలా?"</string>
<string name="user_setup_dialog_message" msgid="269931619868102841">"పరికరాన్ని తీసుకోవడానికి వ్యక్తి అందుబాటులో ఉన్నారని నిర్ధారించుకొని, ఆపై వారికి నిల్వ స్థలాన్ని సెటప్ చేయండి"</string>
@@ -587,11 +591,13 @@
<string name="user_new_profile_name" msgid="2405500423304678841">"కొత్త ప్రొఫైల్"</string>
<string name="user_info_settings_title" msgid="6351390762733279907">"వినియోగదారు సమాచారం"</string>
<string name="profile_info_settings_title" msgid="105699672534365099">"ప్రొఫైల్ సమాచారం"</string>
- <string name="user_need_lock_message" msgid="4311424336209509301">"మీరు పరిమితం చేయబడిన ప్రొఫైల్ను సృష్టించడానికి ముందు, మీ యాప్లు మరియు వ్యక్తిగత డేటాను రక్షించడానికి స్క్రీన్ లాక్ను సెటప్ చేయాల్సి ఉంటుంది."</string>
+ <string name="user_need_lock_message" msgid="4311424336209509301">"మీరు పరిమితం చేయబడిన ప్రొఫైల్ను క్రియేట్ చేయడానికి ముందు, మీ యాప్లు మరియు వ్యక్తిగత డేటాను రక్షించడానికి స్క్రీన్ లాక్ను సెటప్ చేయాల్సి ఉంటుంది."</string>
<string name="user_set_lock_button" msgid="1427128184982594856">"లాక్ను సెట్ చేయి"</string>
<string name="user_switch_to_user" msgid="6975428297154968543">"<xliff:g id="USER_NAME">%s</xliff:g>కు స్విచ్ చేయి"</string>
<string name="creating_new_user_dialog_message" msgid="7232880257538970375">"కొత్త యూజర్ను క్రియేట్ చేస్తోంది…"</string>
+ <string name="creating_new_guest_dialog_message" msgid="1114905602181350690">"కొత్త అతిథిని క్రియేట్ చేస్తోంది…"</string>
<string name="add_user_failed" msgid="4809887794313944872">"కొత్త యూజర్ను క్రియేట్ చేయడం విఫలమైంది"</string>
+ <string name="add_guest_failed" msgid="8074548434469843443">"కొత్త అతిథిని క్రియేట్ చేయడం విఫలమైంది"</string>
<string name="user_nickname" msgid="262624187455825083">"మారుపేరు"</string>
<string name="guest_new_guest" msgid="3482026122932643557">"గెస్ట్ను జోడించండి"</string>
<string name="guest_exit_guest" msgid="5908239569510734136">"గెస్ట్ను తీసివేయండి"</string>
@@ -644,4 +650,7 @@
<string name="dream_complication_title_cast_info" msgid="4038776652841885084">"కాస్ట్ సమాచారం"</string>
<string name="avatar_picker_title" msgid="8492884172713170652">"ప్రొఫైల్ ఫోటోను ఎంచుకోండి"</string>
<string name="default_user_icon_description" msgid="6554047177298972638">"ఆటోమేటిక్ సెట్టింగ్ యూజర్ చిహ్నం"</string>
+ <string name="physical_keyboard_title" msgid="4811935435315835220">"భౌతిక కీబోర్డ్"</string>
+ <string name="keyboard_layout_dialog_title" msgid="3927180147005616290">"కీబోర్డ్ లేఅవుట్ను ఎంచుకోండి"</string>
+ <string name="keyboard_layout_default_label" msgid="1997292217218546957">"ఆటోమేటిక్ సెట్టింగ్"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-th/strings.xml b/packages/SettingsLib/res/values-th/strings.xml
index c2c34ed..900ac51 100644
--- a/packages/SettingsLib/res/values-th/strings.xml
+++ b/packages/SettingsLib/res/values-th/strings.xml
@@ -533,6 +533,8 @@
<string name="accessibility_manual_zen_less_time" msgid="6828877595848229965">"เวลาน้อยลง"</string>
<string name="cancel" msgid="5665114069455378395">"ยกเลิก"</string>
<string name="okay" msgid="949938843324579502">"ตกลง"</string>
+ <!-- no translation found for done (381184316122520313) -->
+ <skip />
<string name="alarms_and_reminders_label" msgid="6918395649731424294">"การปลุกและการช่วยเตือน"</string>
<string name="alarms_and_reminders_switch_title" msgid="4939393911531826222">"อนุญาตให้ตั้งปลุกและการช่วยเตือน"</string>
<string name="alarms_and_reminders_title" msgid="8819933264635406032">"การปลุกและการช่วยเตือน"</string>
@@ -551,7 +553,9 @@
<string name="zen_mode_duration_always_prompt_title" msgid="3212996860498119555">"ถามทุกครั้ง"</string>
<string name="zen_mode_forever" msgid="3339224497605461291">"จนกว่าคุณจะปิด"</string>
<string name="time_unit_just_now" msgid="3006134267292728099">"เมื่อสักครู่"</string>
- <string name="media_transfer_this_device_name" msgid="2357329267148436433">"โทรศัพท์เครื่องนี้"</string>
+ <string name="media_transfer_this_device_name" product="default" msgid="2357329267148436433">"โทรศัพท์เครื่องนี้"</string>
+ <!-- no translation found for media_transfer_this_device_name (3714653244000242800) -->
+ <skip />
<string name="media_transfer_this_phone" msgid="7194341457812151531">"โทรศัพท์เครื่องนี้"</string>
<string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"เกิดปัญหาในการเชื่อมต่อ ปิดอุปกรณ์แล้วเปิดใหม่อีกครั้ง"</string>
<string name="media_transfer_wired_device_name" msgid="4447880899964056007">"อุปกรณ์เสียงแบบมีสาย"</string>
@@ -591,7 +595,9 @@
<string name="user_set_lock_button" msgid="1427128184982594856">"ตั้งค่าล็อก"</string>
<string name="user_switch_to_user" msgid="6975428297154968543">"เปลี่ยนเป็น <xliff:g id="USER_NAME">%s</xliff:g>"</string>
<string name="creating_new_user_dialog_message" msgid="7232880257538970375">"กำลังสร้างผู้ใช้ใหม่…"</string>
+ <string name="creating_new_guest_dialog_message" msgid="1114905602181350690">"กำลังสร้างผู้เข้าร่วมใหม่…"</string>
<string name="add_user_failed" msgid="4809887794313944872">"สร้างผู้ใช้ใหม่ไม่ได้"</string>
+ <string name="add_guest_failed" msgid="8074548434469843443">"สร้างผู้เข้าร่วมใหม่ไม่สำเร็จ"</string>
<string name="user_nickname" msgid="262624187455825083">"ชื่อเล่น"</string>
<string name="guest_new_guest" msgid="3482026122932643557">"เพิ่มผู้ใช้ชั่วคราว"</string>
<string name="guest_exit_guest" msgid="5908239569510734136">"นำผู้ใช้ชั่วคราวออก"</string>
@@ -644,4 +650,7 @@
<string name="dream_complication_title_cast_info" msgid="4038776652841885084">"ข้อมูลแคสต์"</string>
<string name="avatar_picker_title" msgid="8492884172713170652">"เลือกรูปโปรไฟล์"</string>
<string name="default_user_icon_description" msgid="6554047177298972638">"ไอคอนผู้ใช้เริ่มต้น"</string>
+ <string name="physical_keyboard_title" msgid="4811935435315835220">"แป้นพิมพ์จริง"</string>
+ <string name="keyboard_layout_dialog_title" msgid="3927180147005616290">"เลือกรูปแบบแป้นพิมพ์"</string>
+ <string name="keyboard_layout_default_label" msgid="1997292217218546957">"ค่าเริ่มต้น"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-tl/strings.xml b/packages/SettingsLib/res/values-tl/strings.xml
index a8dcb02..5bfb3ef 100644
--- a/packages/SettingsLib/res/values-tl/strings.xml
+++ b/packages/SettingsLib/res/values-tl/strings.xml
@@ -533,6 +533,8 @@
<string name="accessibility_manual_zen_less_time" msgid="6828877595848229965">"Bawasan ang oras."</string>
<string name="cancel" msgid="5665114069455378395">"Kanselahin"</string>
<string name="okay" msgid="949938843324579502">"OK"</string>
+ <!-- no translation found for done (381184316122520313) -->
+ <skip />
<string name="alarms_and_reminders_label" msgid="6918395649731424294">"Mga alarm at paalala"</string>
<string name="alarms_and_reminders_switch_title" msgid="4939393911531826222">"Payagan ang pagtakda ng mga alarm at paalala"</string>
<string name="alarms_and_reminders_title" msgid="8819933264635406032">"Mga alarm at paalala"</string>
@@ -551,7 +553,9 @@
<string name="zen_mode_duration_always_prompt_title" msgid="3212996860498119555">"Magtanong palagi"</string>
<string name="zen_mode_forever" msgid="3339224497605461291">"Hanggang sa i-off mo"</string>
<string name="time_unit_just_now" msgid="3006134267292728099">"Ngayon lang"</string>
- <string name="media_transfer_this_device_name" msgid="2357329267148436433">"Ang teleponong ito"</string>
+ <string name="media_transfer_this_device_name" product="default" msgid="2357329267148436433">"Ang teleponong ito"</string>
+ <!-- no translation found for media_transfer_this_device_name (3714653244000242800) -->
+ <skip />
<string name="media_transfer_this_phone" msgid="7194341457812151531">"Ang teleponong ito"</string>
<string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"Nagkaproblema sa pagkonekta. I-off at pagkatapos ay i-on ang device"</string>
<string name="media_transfer_wired_device_name" msgid="4447880899964056007">"Wired na audio device"</string>
@@ -591,7 +595,9 @@
<string name="user_set_lock_button" msgid="1427128184982594856">"Itakda ang lock"</string>
<string name="user_switch_to_user" msgid="6975428297154968543">"Lumipat sa <xliff:g id="USER_NAME">%s</xliff:g>"</string>
<string name="creating_new_user_dialog_message" msgid="7232880257538970375">"Gumagawa ng bagong user…"</string>
+ <string name="creating_new_guest_dialog_message" msgid="1114905602181350690">"Gumagawa ng bagong guest…"</string>
<string name="add_user_failed" msgid="4809887794313944872">"Hindi nakagawa ng bagong user"</string>
+ <string name="add_guest_failed" msgid="8074548434469843443">"Hindi nakagawa ng bagong guest"</string>
<string name="user_nickname" msgid="262624187455825083">"Nickname"</string>
<string name="guest_new_guest" msgid="3482026122932643557">"Magdagdag ng bisita"</string>
<string name="guest_exit_guest" msgid="5908239569510734136">"Alisin ang bisita"</string>
@@ -644,4 +650,7 @@
<string name="dream_complication_title_cast_info" msgid="4038776652841885084">"Impormasyon ng Cast"</string>
<string name="avatar_picker_title" msgid="8492884172713170652">"Pumili ng larawan sa profile"</string>
<string name="default_user_icon_description" msgid="6554047177298972638">"Icon ng default na user"</string>
+ <string name="physical_keyboard_title" msgid="4811935435315835220">"Pisikal na keyboard"</string>
+ <string name="keyboard_layout_dialog_title" msgid="3927180147005616290">"Pumili ng layout ng keyboard"</string>
+ <string name="keyboard_layout_default_label" msgid="1997292217218546957">"Default"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-tr/strings.xml b/packages/SettingsLib/res/values-tr/strings.xml
index 592bbae..98ed832 100644
--- a/packages/SettingsLib/res/values-tr/strings.xml
+++ b/packages/SettingsLib/res/values-tr/strings.xml
@@ -533,6 +533,8 @@
<string name="accessibility_manual_zen_less_time" msgid="6828877595848229965">"Daha kısa süre."</string>
<string name="cancel" msgid="5665114069455378395">"İptal"</string>
<string name="okay" msgid="949938843324579502">"Tamam"</string>
+ <!-- no translation found for done (381184316122520313) -->
+ <skip />
<string name="alarms_and_reminders_label" msgid="6918395649731424294">"Alarmlar ve hatırlatıcılar"</string>
<string name="alarms_and_reminders_switch_title" msgid="4939393911531826222">"Alarm ve hatırlatıcı ayarlanmasına izin ver"</string>
<string name="alarms_and_reminders_title" msgid="8819933264635406032">"Alarmlar ve hatırlatıcılar"</string>
@@ -551,7 +553,9 @@
<string name="zen_mode_duration_always_prompt_title" msgid="3212996860498119555">"Her zaman sor"</string>
<string name="zen_mode_forever" msgid="3339224497605461291">"Siz kapatana kadar"</string>
<string name="time_unit_just_now" msgid="3006134267292728099">"Az önce"</string>
- <string name="media_transfer_this_device_name" msgid="2357329267148436433">"Bu telefon"</string>
+ <string name="media_transfer_this_device_name" product="default" msgid="2357329267148436433">"Bu telefon"</string>
+ <!-- no translation found for media_transfer_this_device_name (3714653244000242800) -->
+ <skip />
<string name="media_transfer_this_phone" msgid="7194341457812151531">"Bu telefon"</string>
<string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"Bağlanırken sorun oluştu. Cihazı kapatıp tekrar açın"</string>
<string name="media_transfer_wired_device_name" msgid="4447880899964056007">"Kablolu ses cihazı"</string>
@@ -591,7 +595,9 @@
<string name="user_set_lock_button" msgid="1427128184982594856">"Kilidi ayarla"</string>
<string name="user_switch_to_user" msgid="6975428297154968543">"<xliff:g id="USER_NAME">%s</xliff:g> hesabına geç"</string>
<string name="creating_new_user_dialog_message" msgid="7232880257538970375">"Yeni kullanıcı oluşturuluyor…"</string>
+ <string name="creating_new_guest_dialog_message" msgid="1114905602181350690">"Yeni misafir oluşturuluyor…"</string>
<string name="add_user_failed" msgid="4809887794313944872">"Yeni kullanıcı oluşturulamadı"</string>
+ <string name="add_guest_failed" msgid="8074548434469843443">"Yeni misafir oluşturulamadı"</string>
<string name="user_nickname" msgid="262624187455825083">"Takma ad"</string>
<string name="guest_new_guest" msgid="3482026122932643557">"Misafir ekle"</string>
<string name="guest_exit_guest" msgid="5908239569510734136">"Misafir oturumunu kaldır"</string>
@@ -644,4 +650,7 @@
<string name="dream_complication_title_cast_info" msgid="4038776652841885084">"Yayın Bilgisi"</string>
<string name="avatar_picker_title" msgid="8492884172713170652">"Profil fotoğrafı seç"</string>
<string name="default_user_icon_description" msgid="6554047177298972638">"Varsayılan kullanıcı simgesi"</string>
+ <string name="physical_keyboard_title" msgid="4811935435315835220">"Fiziksel klavye"</string>
+ <string name="keyboard_layout_dialog_title" msgid="3927180147005616290">"Klavye düzenini seçin"</string>
+ <string name="keyboard_layout_default_label" msgid="1997292217218546957">"Varsayılan"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-uk/strings.xml b/packages/SettingsLib/res/values-uk/strings.xml
index a219f98..a09dc11 100644
--- a/packages/SettingsLib/res/values-uk/strings.xml
+++ b/packages/SettingsLib/res/values-uk/strings.xml
@@ -533,6 +533,8 @@
<string name="accessibility_manual_zen_less_time" msgid="6828877595848229965">"Менше часу."</string>
<string name="cancel" msgid="5665114069455378395">"Скасувати"</string>
<string name="okay" msgid="949938843324579502">"ОК"</string>
+ <!-- no translation found for done (381184316122520313) -->
+ <skip />
<string name="alarms_and_reminders_label" msgid="6918395649731424294">"Будильники й нагадування"</string>
<string name="alarms_and_reminders_switch_title" msgid="4939393911531826222">"Дозволити встановлювати будильники й нагадування"</string>
<string name="alarms_and_reminders_title" msgid="8819933264635406032">"Будильники й нагадування"</string>
@@ -551,7 +553,9 @@
<string name="zen_mode_duration_always_prompt_title" msgid="3212996860498119555">"Запитувати щоразу"</string>
<string name="zen_mode_forever" msgid="3339224497605461291">"Доки не вимкнути"</string>
<string name="time_unit_just_now" msgid="3006134267292728099">"Щойно"</string>
- <string name="media_transfer_this_device_name" msgid="2357329267148436433">"Цей телефон"</string>
+ <string name="media_transfer_this_device_name" product="default" msgid="2357329267148436433">"Цей телефон"</string>
+ <!-- no translation found for media_transfer_this_device_name (3714653244000242800) -->
+ <skip />
<string name="media_transfer_this_phone" msgid="7194341457812151531">"Цей телефон"</string>
<string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"Не вдається підключитися. Перезавантажте пристрій."</string>
<string name="media_transfer_wired_device_name" msgid="4447880899964056007">"Дротовий аудіопристрій"</string>
@@ -591,7 +595,9 @@
<string name="user_set_lock_button" msgid="1427128184982594856">"Налаштувати блокування"</string>
<string name="user_switch_to_user" msgid="6975428297154968543">"Перейти до користувача <xliff:g id="USER_NAME">%s</xliff:g>"</string>
<string name="creating_new_user_dialog_message" msgid="7232880257538970375">"Створення нового користувача…"</string>
+ <string name="creating_new_guest_dialog_message" msgid="1114905602181350690">"Створення гостя…"</string>
<string name="add_user_failed" msgid="4809887794313944872">"Не вдалося створити користувача"</string>
+ <string name="add_guest_failed" msgid="8074548434469843443">"Не вдалося створити гостя"</string>
<string name="user_nickname" msgid="262624187455825083">"Псевдонім"</string>
<string name="guest_new_guest" msgid="3482026122932643557">"Додати гостя"</string>
<string name="guest_exit_guest" msgid="5908239569510734136">"Видалити гостя"</string>
@@ -644,4 +650,10 @@
<string name="dream_complication_title_cast_info" msgid="4038776652841885084">"Акторський склад"</string>
<string name="avatar_picker_title" msgid="8492884172713170652">"Вибрати зображення профілю"</string>
<string name="default_user_icon_description" msgid="6554047177298972638">"Значок користувача за умовчанням"</string>
+ <!-- no translation found for physical_keyboard_title (4811935435315835220) -->
+ <skip />
+ <!-- no translation found for keyboard_layout_dialog_title (3927180147005616290) -->
+ <skip />
+ <!-- no translation found for keyboard_layout_default_label (1997292217218546957) -->
+ <skip />
</resources>
diff --git a/packages/SettingsLib/res/values-ur/strings.xml b/packages/SettingsLib/res/values-ur/strings.xml
index 3a2d2ef..ab7c517 100644
--- a/packages/SettingsLib/res/values-ur/strings.xml
+++ b/packages/SettingsLib/res/values-ur/strings.xml
@@ -533,6 +533,8 @@
<string name="accessibility_manual_zen_less_time" msgid="6828877595848229965">"کم وقت۔"</string>
<string name="cancel" msgid="5665114069455378395">"منسوخ کریں"</string>
<string name="okay" msgid="949938843324579502">"ٹھیک ہے"</string>
+ <!-- no translation found for done (381184316122520313) -->
+ <skip />
<string name="alarms_and_reminders_label" msgid="6918395649731424294">"الارمز اور یاد دہانیاں"</string>
<string name="alarms_and_reminders_switch_title" msgid="4939393911531826222">"الارمز اور یاد دہانیاں سیٹ کرنے کی اجازت دیں"</string>
<string name="alarms_and_reminders_title" msgid="8819933264635406032">"الارمز اور یاد دہانیاں"</string>
@@ -551,7 +553,9 @@
<string name="zen_mode_duration_always_prompt_title" msgid="3212996860498119555">"ہر بار پوچھیں"</string>
<string name="zen_mode_forever" msgid="3339224497605461291">"یہاں تک کہ آپ آف کر دیں"</string>
<string name="time_unit_just_now" msgid="3006134267292728099">"ابھی ابھی"</string>
- <string name="media_transfer_this_device_name" msgid="2357329267148436433">"یہ فون"</string>
+ <string name="media_transfer_this_device_name" product="default" msgid="2357329267148436433">"یہ فون"</string>
+ <!-- no translation found for media_transfer_this_device_name (3714653244000242800) -->
+ <skip />
<string name="media_transfer_this_phone" msgid="7194341457812151531">"یہ فون"</string>
<string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"منسلک کرنے میں مسئلہ پیش آ گیا۔ آلہ کو آف اور بیک آن کریں"</string>
<string name="media_transfer_wired_device_name" msgid="4447880899964056007">"وائرڈ آڈیو آلہ"</string>
@@ -591,7 +595,9 @@
<string name="user_set_lock_button" msgid="1427128184982594856">"لاک سیٹ کریں"</string>
<string name="user_switch_to_user" msgid="6975428297154968543">"<xliff:g id="USER_NAME">%s</xliff:g> پر سوئچ کریں"</string>
<string name="creating_new_user_dialog_message" msgid="7232880257538970375">"نیا صارف تخلیق ہو رہا ہے…"</string>
+ <string name="creating_new_guest_dialog_message" msgid="1114905602181350690">"نیا مہمان تخلیق کیا جا رہا ہے…"</string>
<string name="add_user_failed" msgid="4809887794313944872">"نیا صارف بنانے میں ناکام"</string>
+ <string name="add_guest_failed" msgid="8074548434469843443">"نیا مہمان بنانے میں ناکام"</string>
<string name="user_nickname" msgid="262624187455825083">"عرفی نام"</string>
<string name="guest_new_guest" msgid="3482026122932643557">"مہمان کو شامل کریں"</string>
<string name="guest_exit_guest" msgid="5908239569510734136">"مہمان کو ہٹائیں"</string>
@@ -644,4 +650,7 @@
<string name="dream_complication_title_cast_info" msgid="4038776652841885084">"کاسٹ کرنے کی معلومات"</string>
<string name="avatar_picker_title" msgid="8492884172713170652">"پروفائل کی تصویر منتخب کریں"</string>
<string name="default_user_icon_description" msgid="6554047177298972638">"ڈیفالٹ صارف کا آئیکن"</string>
+ <string name="physical_keyboard_title" msgid="4811935435315835220">"فزیکل کی بورڈ"</string>
+ <string name="keyboard_layout_dialog_title" msgid="3927180147005616290">"کی بورڈ لے آؤٹ منتخب کریں"</string>
+ <string name="keyboard_layout_default_label" msgid="1997292217218546957">"ڈیفالٹ"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-uz/strings.xml b/packages/SettingsLib/res/values-uz/strings.xml
index 3e3db69..c1748a3 100644
--- a/packages/SettingsLib/res/values-uz/strings.xml
+++ b/packages/SettingsLib/res/values-uz/strings.xml
@@ -533,6 +533,8 @@
<string name="accessibility_manual_zen_less_time" msgid="6828877595848229965">"Kamroq vaqt."</string>
<string name="cancel" msgid="5665114069455378395">"Bekor qilish"</string>
<string name="okay" msgid="949938843324579502">"OK"</string>
+ <!-- no translation found for done (381184316122520313) -->
+ <skip />
<string name="alarms_and_reminders_label" msgid="6918395649731424294">"Signal va eslatmalar"</string>
<string name="alarms_and_reminders_switch_title" msgid="4939393911531826222">"Signal va eslatmalarni sozlashga ruxsat berish"</string>
<string name="alarms_and_reminders_title" msgid="8819933264635406032">"Signal va eslatmalar"</string>
@@ -551,7 +553,9 @@
<string name="zen_mode_duration_always_prompt_title" msgid="3212996860498119555">"Har safar so‘ralsin"</string>
<string name="zen_mode_forever" msgid="3339224497605461291">"Rejimdan chiqilgunicha"</string>
<string name="time_unit_just_now" msgid="3006134267292728099">"Hozir"</string>
- <string name="media_transfer_this_device_name" msgid="2357329267148436433">"Shu telefon"</string>
+ <string name="media_transfer_this_device_name" product="default" msgid="2357329267148436433">"Shu telefon"</string>
+ <!-- no translation found for media_transfer_this_device_name (3714653244000242800) -->
+ <skip />
<string name="media_transfer_this_phone" msgid="7194341457812151531">"Shu telefon"</string>
<string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"Ulanishda muammo yuz berdi. Qurilmani oʻchiring va yoqing"</string>
<string name="media_transfer_wired_device_name" msgid="4447880899964056007">"Simli audio qurilma"</string>
@@ -591,7 +595,9 @@
<string name="user_set_lock_button" msgid="1427128184982594856">"Qulf o‘rnatish"</string>
<string name="user_switch_to_user" msgid="6975428297154968543">"Bunga almashish: <xliff:g id="USER_NAME">%s</xliff:g>"</string>
<string name="creating_new_user_dialog_message" msgid="7232880257538970375">"Yangi foydalanuvchi yaratilmoqda…"</string>
+ <string name="creating_new_guest_dialog_message" msgid="1114905602181350690">"Yangi mehmon yaratilmoqda…"</string>
<string name="add_user_failed" msgid="4809887794313944872">"Yangi foydalanuvchi yaratilmadi"</string>
+ <string name="add_guest_failed" msgid="8074548434469843443">"Yangi mehmon yaratilmadi"</string>
<string name="user_nickname" msgid="262624187455825083">"Nik"</string>
<string name="guest_new_guest" msgid="3482026122932643557">"Mehmon kiritish"</string>
<string name="guest_exit_guest" msgid="5908239569510734136">"Mehmonni olib tashlash"</string>
@@ -644,4 +650,7 @@
<string name="dream_complication_title_cast_info" msgid="4038776652841885084">"Translatsiya axboroti"</string>
<string name="avatar_picker_title" msgid="8492884172713170652">"Profil rasmini tanlash"</string>
<string name="default_user_icon_description" msgid="6554047177298972638">"Foydalanuvchining standart belgisi"</string>
+ <string name="physical_keyboard_title" msgid="4811935435315835220">"Tashqi klaviatura"</string>
+ <string name="keyboard_layout_dialog_title" msgid="3927180147005616290">"Klaviatura sxemasini tanlang"</string>
+ <string name="keyboard_layout_default_label" msgid="1997292217218546957">"Asosiy"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-vi/strings.xml b/packages/SettingsLib/res/values-vi/strings.xml
index 2094400..419f1da 100644
--- a/packages/SettingsLib/res/values-vi/strings.xml
+++ b/packages/SettingsLib/res/values-vi/strings.xml
@@ -533,6 +533,8 @@
<string name="accessibility_manual_zen_less_time" msgid="6828877595848229965">"Ít thời gian hơn."</string>
<string name="cancel" msgid="5665114069455378395">"Hủy"</string>
<string name="okay" msgid="949938843324579502">"OK"</string>
+ <!-- no translation found for done (381184316122520313) -->
+ <skip />
<string name="alarms_and_reminders_label" msgid="6918395649731424294">"Chuông báo và lời nhắc"</string>
<string name="alarms_and_reminders_switch_title" msgid="4939393911531826222">"Cho phép đặt chuông báo và lời nhắc"</string>
<string name="alarms_and_reminders_title" msgid="8819933264635406032">"Chuông báo và lời nhắc"</string>
@@ -551,7 +553,9 @@
<string name="zen_mode_duration_always_prompt_title" msgid="3212996860498119555">"Luôn hỏi"</string>
<string name="zen_mode_forever" msgid="3339224497605461291">"Cho đến khi bạn tắt"</string>
<string name="time_unit_just_now" msgid="3006134267292728099">"Vừa xong"</string>
- <string name="media_transfer_this_device_name" msgid="2357329267148436433">"Điện thoại này"</string>
+ <string name="media_transfer_this_device_name" product="default" msgid="2357329267148436433">"Điện thoại này"</string>
+ <!-- no translation found for media_transfer_this_device_name (3714653244000242800) -->
+ <skip />
<string name="media_transfer_this_phone" msgid="7194341457812151531">"Điện thoại này"</string>
<string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"Sự cố kết nối. Hãy tắt thiết bị rồi bật lại"</string>
<string name="media_transfer_wired_device_name" msgid="4447880899964056007">"Thiết bị âm thanh có dây"</string>
@@ -591,7 +595,9 @@
<string name="user_set_lock_button" msgid="1427128184982594856">"Thiết lập khóa"</string>
<string name="user_switch_to_user" msgid="6975428297154968543">"Chuyển sang <xliff:g id="USER_NAME">%s</xliff:g>"</string>
<string name="creating_new_user_dialog_message" msgid="7232880257538970375">"Đang tạo người dùng mới…"</string>
+ <string name="creating_new_guest_dialog_message" msgid="1114905602181350690">"Đang tạo khách mới…"</string>
<string name="add_user_failed" msgid="4809887794313944872">"Không tạo được người dùng mới"</string>
+ <string name="add_guest_failed" msgid="8074548434469843443">"Không tạo được khách mới"</string>
<string name="user_nickname" msgid="262624187455825083">"Biệt hiệu"</string>
<string name="guest_new_guest" msgid="3482026122932643557">"Thêm khách"</string>
<string name="guest_exit_guest" msgid="5908239569510734136">"Xóa phiên khách"</string>
@@ -644,4 +650,7 @@
<string name="dream_complication_title_cast_info" msgid="4038776652841885084">"Thông tin về dàn nghệ sĩ"</string>
<string name="avatar_picker_title" msgid="8492884172713170652">"Chọn một ảnh hồ sơ"</string>
<string name="default_user_icon_description" msgid="6554047177298972638">"Biểu tượng người dùng mặc định"</string>
+ <string name="physical_keyboard_title" msgid="4811935435315835220">"Bàn phím thực"</string>
+ <string name="keyboard_layout_dialog_title" msgid="3927180147005616290">"Chọn bố cục bàn phím"</string>
+ <string name="keyboard_layout_default_label" msgid="1997292217218546957">"Mặc định"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-zh-rCN/strings.xml b/packages/SettingsLib/res/values-zh-rCN/strings.xml
index 6d5b8e1..592e69c 100644
--- a/packages/SettingsLib/res/values-zh-rCN/strings.xml
+++ b/packages/SettingsLib/res/values-zh-rCN/strings.xml
@@ -533,6 +533,8 @@
<string name="accessibility_manual_zen_less_time" msgid="6828877595848229965">"减少时间。"</string>
<string name="cancel" msgid="5665114069455378395">"取消"</string>
<string name="okay" msgid="949938843324579502">"确定"</string>
+ <!-- no translation found for done (381184316122520313) -->
+ <skip />
<string name="alarms_and_reminders_label" msgid="6918395649731424294">"闹钟和提醒"</string>
<string name="alarms_and_reminders_switch_title" msgid="4939393911531826222">"允许设置闹钟和提醒"</string>
<string name="alarms_and_reminders_title" msgid="8819933264635406032">"闹钟和提醒"</string>
@@ -551,7 +553,9 @@
<string name="zen_mode_duration_always_prompt_title" msgid="3212996860498119555">"每次都询问"</string>
<string name="zen_mode_forever" msgid="3339224497605461291">"直到您将其关闭"</string>
<string name="time_unit_just_now" msgid="3006134267292728099">"刚刚"</string>
- <string name="media_transfer_this_device_name" msgid="2357329267148436433">"这部手机"</string>
+ <string name="media_transfer_this_device_name" product="default" msgid="2357329267148436433">"这部手机"</string>
+ <!-- no translation found for media_transfer_this_device_name (3714653244000242800) -->
+ <skip />
<string name="media_transfer_this_phone" msgid="7194341457812151531">"这部手机"</string>
<string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"连接时遇到问题。请关闭并重新开启设备"</string>
<string name="media_transfer_wired_device_name" msgid="4447880899964056007">"有线音频设备"</string>
@@ -591,7 +595,9 @@
<string name="user_set_lock_button" msgid="1427128184982594856">"设置屏幕锁定方式"</string>
<string name="user_switch_to_user" msgid="6975428297154968543">"切换到<xliff:g id="USER_NAME">%s</xliff:g>"</string>
<string name="creating_new_user_dialog_message" msgid="7232880257538970375">"正在创建新用户…"</string>
+ <string name="creating_new_guest_dialog_message" msgid="1114905602181350690">"正在创建新的访客…"</string>
<string name="add_user_failed" msgid="4809887794313944872">"无法创建新用户"</string>
+ <string name="add_guest_failed" msgid="8074548434469843443">"未能创建新的访客"</string>
<string name="user_nickname" msgid="262624187455825083">"昵称"</string>
<string name="guest_new_guest" msgid="3482026122932643557">"添加访客"</string>
<string name="guest_exit_guest" msgid="5908239569510734136">"移除访客"</string>
@@ -644,4 +650,7 @@
<string name="dream_complication_title_cast_info" msgid="4038776652841885084">"投射信息"</string>
<string name="avatar_picker_title" msgid="8492884172713170652">"选择个人资料照片"</string>
<string name="default_user_icon_description" msgid="6554047177298972638">"默认用户图标"</string>
+ <string name="physical_keyboard_title" msgid="4811935435315835220">"实体键盘"</string>
+ <string name="keyboard_layout_dialog_title" msgid="3927180147005616290">"选择键盘布局"</string>
+ <string name="keyboard_layout_default_label" msgid="1997292217218546957">"默认"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-zh-rHK/strings.xml b/packages/SettingsLib/res/values-zh-rHK/strings.xml
index d18c0c9..41f3994 100644
--- a/packages/SettingsLib/res/values-zh-rHK/strings.xml
+++ b/packages/SettingsLib/res/values-zh-rHK/strings.xml
@@ -533,6 +533,8 @@
<string name="accessibility_manual_zen_less_time" msgid="6828877595848229965">"減少時間。"</string>
<string name="cancel" msgid="5665114069455378395">"取消"</string>
<string name="okay" msgid="949938843324579502">"確定"</string>
+ <!-- no translation found for done (381184316122520313) -->
+ <skip />
<string name="alarms_and_reminders_label" msgid="6918395649731424294">"鬧鐘和提醒"</string>
<string name="alarms_and_reminders_switch_title" msgid="4939393911531826222">"允許設定鬧鐘和提醒"</string>
<string name="alarms_and_reminders_title" msgid="8819933264635406032">"鬧鐘和提醒"</string>
@@ -551,7 +553,9 @@
<string name="zen_mode_duration_always_prompt_title" msgid="3212996860498119555">"每次都詢問"</string>
<string name="zen_mode_forever" msgid="3339224497605461291">"直至您關閉為止"</string>
<string name="time_unit_just_now" msgid="3006134267292728099">"剛剛"</string>
- <string name="media_transfer_this_device_name" msgid="2357329267148436433">"此手機"</string>
+ <string name="media_transfer_this_device_name" product="default" msgid="2357329267148436433">"此手機"</string>
+ <!-- no translation found for media_transfer_this_device_name (3714653244000242800) -->
+ <skip />
<string name="media_transfer_this_phone" msgid="7194341457812151531">"這部手機"</string>
<string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"無法連接,請關閉裝置然後重新開機"</string>
<string name="media_transfer_wired_device_name" msgid="4447880899964056007">"有線音響裝置"</string>
@@ -591,7 +595,9 @@
<string name="user_set_lock_button" msgid="1427128184982594856">"設定上鎖畫面"</string>
<string name="user_switch_to_user" msgid="6975428297154968543">"切換至<xliff:g id="USER_NAME">%s</xliff:g>"</string>
<string name="creating_new_user_dialog_message" msgid="7232880257538970375">"正在建立新使用者…"</string>
+ <string name="creating_new_guest_dialog_message" msgid="1114905602181350690">"正在建立新訪客…"</string>
<string name="add_user_failed" msgid="4809887794313944872">"無法建立新使用者"</string>
+ <string name="add_guest_failed" msgid="8074548434469843443">"無法建立新訪客"</string>
<string name="user_nickname" msgid="262624187455825083">"暱稱"</string>
<string name="guest_new_guest" msgid="3482026122932643557">"新增訪客"</string>
<string name="guest_exit_guest" msgid="5908239569510734136">"移除訪客"</string>
@@ -644,4 +650,7 @@
<string name="dream_complication_title_cast_info" msgid="4038776652841885084">"投放資料"</string>
<string name="avatar_picker_title" msgid="8492884172713170652">"選擇個人檔案相片"</string>
<string name="default_user_icon_description" msgid="6554047177298972638">"預設使用者圖示"</string>
+ <string name="physical_keyboard_title" msgid="4811935435315835220">"實體鍵盤"</string>
+ <string name="keyboard_layout_dialog_title" msgid="3927180147005616290">"選擇鍵盤配置"</string>
+ <string name="keyboard_layout_default_label" msgid="1997292217218546957">"預設"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-zh-rTW/strings.xml b/packages/SettingsLib/res/values-zh-rTW/strings.xml
index bec3c93..975e650 100644
--- a/packages/SettingsLib/res/values-zh-rTW/strings.xml
+++ b/packages/SettingsLib/res/values-zh-rTW/strings.xml
@@ -533,6 +533,8 @@
<string name="accessibility_manual_zen_less_time" msgid="6828877595848229965">"減少時間。"</string>
<string name="cancel" msgid="5665114069455378395">"取消"</string>
<string name="okay" msgid="949938843324579502">"確定"</string>
+ <!-- no translation found for done (381184316122520313) -->
+ <skip />
<string name="alarms_and_reminders_label" msgid="6918395649731424294">"鬧鐘與提醒"</string>
<string name="alarms_and_reminders_switch_title" msgid="4939393911531826222">"允許設定鬧鐘和提醒"</string>
<string name="alarms_and_reminders_title" msgid="8819933264635406032">"鬧鐘和提醒"</string>
@@ -551,7 +553,9 @@
<string name="zen_mode_duration_always_prompt_title" msgid="3212996860498119555">"每次都詢問"</string>
<string name="zen_mode_forever" msgid="3339224497605461291">"直到你關閉為止"</string>
<string name="time_unit_just_now" msgid="3006134267292728099">"剛剛"</string>
- <string name="media_transfer_this_device_name" msgid="2357329267148436433">"這支手機"</string>
+ <string name="media_transfer_this_device_name" product="default" msgid="2357329267148436433">"這支手機"</string>
+ <!-- no translation found for media_transfer_this_device_name (3714653244000242800) -->
+ <skip />
<string name="media_transfer_this_phone" msgid="7194341457812151531">"這支手機"</string>
<string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"無法連線,請關閉裝置後再重新開啟"</string>
<string name="media_transfer_wired_device_name" msgid="4447880899964056007">"有線音訊裝置"</string>
@@ -591,7 +595,9 @@
<string name="user_set_lock_button" msgid="1427128184982594856">"設定鎖定"</string>
<string name="user_switch_to_user" msgid="6975428297154968543">"切換至<xliff:g id="USER_NAME">%s</xliff:g>"</string>
<string name="creating_new_user_dialog_message" msgid="7232880257538970375">"正在建立新使用者…"</string>
+ <string name="creating_new_guest_dialog_message" msgid="1114905602181350690">"正在建立新訪客…"</string>
<string name="add_user_failed" msgid="4809887794313944872">"無法建立新的使用者"</string>
+ <string name="add_guest_failed" msgid="8074548434469843443">"無法建立新訪客"</string>
<string name="user_nickname" msgid="262624187455825083">"暱稱"</string>
<string name="guest_new_guest" msgid="3482026122932643557">"新增訪客"</string>
<string name="guest_exit_guest" msgid="5908239569510734136">"移除訪客"</string>
@@ -644,4 +650,7 @@
<string name="dream_complication_title_cast_info" msgid="4038776652841885084">"演出者資訊"</string>
<string name="avatar_picker_title" msgid="8492884172713170652">"選擇個人資料相片"</string>
<string name="default_user_icon_description" msgid="6554047177298972638">"預設使用者圖示"</string>
+ <string name="physical_keyboard_title" msgid="4811935435315835220">"實體鍵盤"</string>
+ <string name="keyboard_layout_dialog_title" msgid="3927180147005616290">"選擇鍵盤配置"</string>
+ <string name="keyboard_layout_default_label" msgid="1997292217218546957">"預設"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-zu/strings.xml b/packages/SettingsLib/res/values-zu/strings.xml
index 16b601c..119c91b 100644
--- a/packages/SettingsLib/res/values-zu/strings.xml
+++ b/packages/SettingsLib/res/values-zu/strings.xml
@@ -533,6 +533,8 @@
<string name="accessibility_manual_zen_less_time" msgid="6828877595848229965">"Isikhathi esincane."</string>
<string name="cancel" msgid="5665114069455378395">"Khansela"</string>
<string name="okay" msgid="949938843324579502">"KULUNGILE"</string>
+ <!-- no translation found for done (381184316122520313) -->
+ <skip />
<string name="alarms_and_reminders_label" msgid="6918395649731424294">"Ama-alamu nezikhumbuzi"</string>
<string name="alarms_and_reminders_switch_title" msgid="4939393911531826222">"Vumela ukusetha ama-alamu nezikhumbuzi"</string>
<string name="alarms_and_reminders_title" msgid="8819933264635406032">"Ama-alamu nezikhumbuzi"</string>
@@ -551,7 +553,9 @@
<string name="zen_mode_duration_always_prompt_title" msgid="3212996860498119555">"Buza njalo"</string>
<string name="zen_mode_forever" msgid="3339224497605461291">"Uze uvale isikrini"</string>
<string name="time_unit_just_now" msgid="3006134267292728099">"Khona manje"</string>
- <string name="media_transfer_this_device_name" msgid="2357329267148436433">"Le foni"</string>
+ <string name="media_transfer_this_device_name" product="default" msgid="2357329267148436433">"Le foni"</string>
+ <!-- no translation found for media_transfer_this_device_name (3714653244000242800) -->
+ <skip />
<string name="media_transfer_this_phone" msgid="7194341457812151531">"Le foni"</string>
<string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"Inkinga yokuxhumeka. Vala idivayisi futhi uphinde uyivule"</string>
<string name="media_transfer_wired_device_name" msgid="4447880899964056007">"Idivayisi yomsindo enentambo"</string>
@@ -591,7 +595,9 @@
<string name="user_set_lock_button" msgid="1427128184982594856">"Setha ukukhiya"</string>
<string name="user_switch_to_user" msgid="6975428297154968543">"Shintshela ku-<xliff:g id="USER_NAME">%s</xliff:g>"</string>
<string name="creating_new_user_dialog_message" msgid="7232880257538970375">"Idala umsebenzisi omusha…"</string>
+ <string name="creating_new_guest_dialog_message" msgid="1114905602181350690">"Isungula isimenywa esisha…"</string>
<string name="add_user_failed" msgid="4809887794313944872">"Yehlulekile ukudala umsebenzisi omusha"</string>
+ <string name="add_guest_failed" msgid="8074548434469843443">"Yehlulekile ukusungula isimenywa esisha"</string>
<string name="user_nickname" msgid="262624187455825083">"Isiteketiso"</string>
<string name="guest_new_guest" msgid="3482026122932643557">"Engeza isivakashi"</string>
<string name="guest_exit_guest" msgid="5908239569510734136">"Susa isihambeli"</string>
@@ -644,4 +650,7 @@
<string name="dream_complication_title_cast_info" msgid="4038776652841885084">"Ulwazi Lokusakaza"</string>
<string name="avatar_picker_title" msgid="8492884172713170652">"Khetha isithombe sephrofayela"</string>
<string name="default_user_icon_description" msgid="6554047177298972638">"Isithonjana somsebenzisi sokuzenzakalelayo"</string>
+ <string name="physical_keyboard_title" msgid="4811935435315835220">"Ikhibhodi ephathekayo"</string>
+ <string name="keyboard_layout_dialog_title" msgid="3927180147005616290">"Khetha isendlalelo sekhibhodi"</string>
+ <string name="keyboard_layout_default_label" msgid="1997292217218546957">"Zenzekela"</string>
</resources>
diff --git a/packages/SettingsLib/res/values/strings.xml b/packages/SettingsLib/res/values/strings.xml
index bd70396..31036ec 100644
--- a/packages/SettingsLib/res/values/strings.xml
+++ b/packages/SettingsLib/res/values/strings.xml
@@ -1038,23 +1038,6 @@
<!-- Developer settings: text for the WebView provider selection toast shown if an invalid provider was chosen (i.e. the setting list was stale). [CHAR LIMIT=NONE] -->
<string name="select_webview_provider_toast_text">This choice is no longer valid. Try again.</string>
- <!-- Developer settings screen, convert userdata to file encryption option name -->
- <string name="convert_to_file_encryption">Convert to file encryption</string>
- <!-- Developer settings screen, convert userdata to file encryption summary when option is available -->
- <string name="convert_to_file_encryption_enabled">Convert\u2026</string>
- <!-- Developer settings screen, convert userdata to file encryption summary when option is already done -->
- <string name="convert_to_file_encryption_done">Already file encrypted</string>
- <!-- Title used on dialog with final prompt for converting to file encryption -->
- <string name="title_convert_fbe">Converting to file based encryption</string>
- <!-- Warning displayed on dialog with final prompt for converting to file encryption -->
- <string name="convert_to_fbe_warning">
- Convert data partition to file based encryption.\n
- !!Warning!! This will erase all your data.\n
- This feature is alpha, and may not work correctly.\n
- Press \'Wipe and convert\u2026\' to continue.</string>
- <!-- Button on dialog that triggers convertion to file encryption -->
- <string name="button_convert_fbe">Wipe and convert\u2026</string>
-
<!-- Name of feature to change color setting for the display [CHAR LIMIT=60] -->
<string name="picture_color_mode">Picture color mode</string>
@@ -1344,7 +1327,9 @@
<string name="notice_header" translatable="false"></string>
<!-- Name of the phone device. [CHAR LIMIT=30] -->
- <string name="media_transfer_this_device_name">This phone</string>
+ <string name="media_transfer_this_device_name" product="default">This phone</string>
+ <!-- Name of the tablet device. [CHAR LIMIT=30] -->
+ <string name="media_transfer_this_device_name" product="tablet">This tablet</string>
<!-- Name of the phone device with an active remote session. [CHAR LIMIT=30] -->
<string name="media_transfer_this_phone">This phone</string>
@@ -1580,4 +1565,11 @@
<string name="keyboard_layout_dialog_title">Choose keyboard layout</string>
<!-- Label of the default keyboard layout. [CHAR LIMIT=35] -->
<string name="keyboard_layout_default_label">Default</string>
+
+ <!-- Special access > Title for managing turn screen on settings. [CHAR LIMIT=50] -->
+ <string name="turn_screen_on_title">Turn screen on</string>
+ <!-- Label for a setting which controls whether an app can turn the screen on [CHAR LIMIT=45] -->
+ <string name="allow_turn_screen_on">Allow turning the screen on</string>
+ <!-- Description for a setting which controls whether an app can turn the screen on [CHAR LIMIT=NONE] -->
+ <string name="allow_turn_screen_on_description">Allow an app to turn the screen on. If granted, the app may turn on the screen at any time without your explicit intent.</string>
</resources>
diff --git a/packages/SettingsLib/src/com/android/settingslib/RestrictedPreferenceHelper.java b/packages/SettingsLib/src/com/android/settingslib/RestrictedPreferenceHelper.java
index e4efae2..3a4a8d2 100644
--- a/packages/SettingsLib/src/com/android/settingslib/RestrictedPreferenceHelper.java
+++ b/packages/SettingsLib/src/com/android/settingslib/RestrictedPreferenceHelper.java
@@ -23,12 +23,15 @@
import android.app.admin.DevicePolicyManager;
import android.content.Context;
import android.content.res.TypedArray;
+import android.os.Build;
import android.os.UserHandle;
import android.text.TextUtils;
import android.util.AttributeSet;
import android.util.TypedValue;
import android.widget.TextView;
+import androidx.annotation.RequiresApi;
+import androidx.core.os.BuildCompat;
import androidx.preference.Preference;
import androidx.preference.PreferenceViewHolder;
@@ -102,11 +105,9 @@
if (mDisabledSummary) {
final TextView summaryView = (TextView) holder.findViewById(android.R.id.summary);
if (summaryView != null) {
- final CharSequence disabledText = mContext
- .getSystemService(DevicePolicyManager.class)
- .getString(CONTROLLED_BY_ADMIN_SUMMARY,
- () -> summaryView.getContext().getString(
- R.string.disabled_by_admin_summary_text));
+ final CharSequence disabledText = BuildCompat.isAtLeastT()
+ ? getDisabledByAdminUpdatableString()
+ : mContext.getString(R.string.disabled_by_admin_summary_text);
if (mDisabledByAdmin) {
summaryView.setText(disabledText);
} else if (mDisabledByAppOps) {
@@ -119,6 +120,13 @@
}
}
+ @RequiresApi(Build.VERSION_CODES.TIRAMISU)
+ private String getDisabledByAdminUpdatableString() {
+ return mContext.getSystemService(DevicePolicyManager.class).getResources().getString(
+ CONTROLLED_BY_ADMIN_SUMMARY,
+ () -> mContext.getString(R.string.disabled_by_admin_summary_text));
+ }
+
public void useAdminDisabledSummary(boolean useSummary) {
mDisabledSummary = useSummary;
}
diff --git a/packages/SettingsLib/src/com/android/settingslib/Utils.java b/packages/SettingsLib/src/com/android/settingslib/Utils.java
index 19114cf..f639022 100644
--- a/packages/SettingsLib/src/com/android/settingslib/Utils.java
+++ b/packages/SettingsLib/src/com/android/settingslib/Utils.java
@@ -30,6 +30,7 @@
import android.net.vcn.VcnTransportInfo;
import android.net.wifi.WifiInfo;
import android.os.BatteryManager;
+import android.os.Build;
import android.os.SystemProperties;
import android.os.UserHandle;
import android.os.UserManager;
@@ -41,8 +42,10 @@
import android.telephony.TelephonyManager;
import androidx.annotation.NonNull;
+import androidx.annotation.RequiresApi;
import androidx.core.graphics.drawable.RoundedBitmapDrawable;
import androidx.core.graphics.drawable.RoundedBitmapDrawableFactory;
+import androidx.core.os.BuildCompat;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.util.UserIcons;
@@ -127,8 +130,9 @@
String name = info != null ? info.name : null;
if (info.isManagedProfile()) {
// We use predefined values for managed profiles
- return context.getSystemService(DevicePolicyManager.class).getString(
- WORK_PROFILE_USER_LABEL, () -> context.getString(R.string.managed_user_title));
+ return BuildCompat.isAtLeastT()
+ ? getUpdatableManagedUserTitle(context)
+ : context.getString(R.string.managed_user_title);
} else if (info.isGuest()) {
name = context.getString(R.string.user_guest);
}
@@ -140,6 +144,13 @@
return context.getResources().getString(R.string.running_process_item_user_label, name);
}
+ @RequiresApi(Build.VERSION_CODES.TIRAMISU)
+ private static String getUpdatableManagedUserTitle(Context context) {
+ return context.getSystemService(DevicePolicyManager.class).getResources().getString(
+ WORK_PROFILE_USER_LABEL,
+ () -> context.getString(R.string.managed_user_title));
+ }
+
/**
* Returns a circular icon for a user.
*/
diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/BluetoothEventManager.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/BluetoothEventManager.java
index 389892e..62c83cf 100644
--- a/packages/SettingsLib/src/com/android/settingslib/bluetooth/BluetoothEventManager.java
+++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/BluetoothEventManager.java
@@ -371,7 +371,7 @@
|| cachedDevice.getHiSyncId() != BluetoothHearingAid.HI_SYNC_ID_INVALID) {
mDeviceManager.onDeviceUnpaired(cachedDevice);
}
- int reason = intent.getIntExtra(BluetoothDevice.EXTRA_REASON,
+ int reason = intent.getIntExtra(BluetoothDevice.EXTRA_UNBOND_REASON,
BluetoothDevice.ERROR);
showUnbondMessage(context, cachedDevice.getName(), reason);
diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDevice.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDevice.java
index 3d91c5a..2a28891 100644
--- a/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDevice.java
+++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDevice.java
@@ -753,7 +753,10 @@
ParcelUuid[] uuids = mDevice.getUuids();
if (uuids == null) return false;
- ParcelUuid[] localUuids = mLocalAdapter.getUuids();
+ List<ParcelUuid> uuidsList = mLocalAdapter.getUuidsList();
+ ParcelUuid[] localUuids = new ParcelUuid[uuidsList.size()];
+ uuidsList.toArray(localUuids);
+
if (localUuids == null) return false;
/*
@@ -1117,7 +1120,8 @@
final boolean isOnCall = Utils.isAudioModeOngoingCall(mContext);
if ((mIsActiveDeviceHearingAid)
|| (mIsActiveDeviceHeadset && isOnCall)
- || (mIsActiveDeviceA2dp && !isOnCall)) {
+ || (mIsActiveDeviceA2dp && !isOnCall)
+ || mIsActiveDeviceLeAudio) {
if (isTwsBatteryAvailable(leftBattery, rightBattery) && !shortSummary) {
stringRes = R.string.bluetooth_active_battery_level_untethered;
} else if (batteryLevelPercentageString != null && !shortSummary) {
diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/LeAudioProfile.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/LeAudioProfile.java
index e203cba..19df1e9 100644
--- a/packages/SettingsLib/src/com/android/settingslib/bluetooth/LeAudioProfile.java
+++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/LeAudioProfile.java
@@ -246,6 +246,13 @@
return R.drawable.ic_bt_le_audio;
}
+ public int getAudioLocation(BluetoothDevice device) {
+ if (mService == null || device == null) {
+ return BluetoothLeAudio.AUDIO_LOCATION_INVALID;
+ }
+ return mService.getAudioLocation(device);
+ }
+
@RequiresApi(Build.VERSION_CODES.S)
protected void finalize() {
if (DEBUG) {
diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/LocalBluetoothAdapter.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/LocalBluetoothAdapter.java
index e7a6b32..31cc6a4 100644
--- a/packages/SettingsLib/src/com/android/settingslib/bluetooth/LocalBluetoothAdapter.java
+++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/LocalBluetoothAdapter.java
@@ -126,7 +126,10 @@
}
public ParcelUuid[] getUuids() {
- return mAdapter.getUuids();
+ List<ParcelUuid> uuidsList = mAdapter.getUuidsList();
+ ParcelUuid[] uuidsArray = new ParcelUuid[uuidsList.size()];
+ uuidsList.toArray(uuidsArray);
+ return uuidsArray;
}
public boolean isDiscovering() {
diff --git a/packages/SettingsLib/src/com/android/settingslib/connectivity/ConnectivitySubsystemsRecoveryManager.java b/packages/SettingsLib/src/com/android/settingslib/connectivity/ConnectivitySubsystemsRecoveryManager.java
index c61f8a9..be420ac 100644
--- a/packages/SettingsLib/src/com/android/settingslib/connectivity/ConnectivitySubsystemsRecoveryManager.java
+++ b/packages/SettingsLib/src/com/android/settingslib/connectivity/ConnectivitySubsystemsRecoveryManager.java
@@ -31,6 +31,8 @@
import android.telephony.TelephonyManager;
import android.util.Log;
+import androidx.annotation.VisibleForTesting;
+
/**
* An interface class to manage connectivity subsystem recovery/restart operations.
*/
@@ -193,22 +195,30 @@
mApmMonitorRegistered = false;
}
- private void startTrackingWifiRestart() {
+ @VisibleForTesting
+ void startTrackingWifiRestart() {
+ if (mWifiManager == null) return;
mWifiManager.registerSubsystemRestartTrackingCallback(new HandlerExecutor(mHandler),
mWifiSubsystemRestartTrackingCallback);
}
- private void stopTrackingWifiRestart() {
+ @VisibleForTesting
+ void stopTrackingWifiRestart() {
+ if (mWifiManager == null) return;
mWifiManager.unregisterSubsystemRestartTrackingCallback(
mWifiSubsystemRestartTrackingCallback);
}
- private void startTrackingTelephonyRestart() {
+ @VisibleForTesting
+ void startTrackingTelephonyRestart() {
+ if (mTelephonyManager == null) return;
mTelephonyManager.registerTelephonyCallback(new HandlerExecutor(mHandler),
mTelephonyCallback);
}
- private void stopTrackingTelephonyRestart() {
+ @VisibleForTesting
+ void stopTrackingTelephonyRestart() {
+ if (mTelephonyManager == null) return;
mTelephonyManager.unregisterTelephonyCallback(mTelephonyCallback);
}
diff --git a/packages/SettingsLib/src/com/android/settingslib/drawable/UserIconDrawable.java b/packages/SettingsLib/src/com/android/settingslib/drawable/UserIconDrawable.java
index d01f2b4..94d90a8 100644
--- a/packages/SettingsLib/src/com/android/settingslib/drawable/UserIconDrawable.java
+++ b/packages/SettingsLib/src/com/android/settingslib/drawable/UserIconDrawable.java
@@ -98,7 +98,7 @@
@RequiresApi(Build.VERSION_CODES.TIRAMISU)
private static Drawable getUpdatableManagedUserDrawable(Context context) {
DevicePolicyManager dpm = context.getSystemService(DevicePolicyManager.class);
- return dpm.getDrawableForDensity(
+ return dpm.getResources().getDrawableForDensity(
WORK_PROFILE_USER_ICON,
SOLID_COLORED,
context.getResources().getDisplayMetrics().densityDpi,
@@ -233,7 +233,7 @@
@RequiresApi(Build.VERSION_CODES.TIRAMISU)
private static Drawable getUpdatableManagementBadge(Context context) {
DevicePolicyManager dpm = context.getSystemService(DevicePolicyManager.class);
- return dpm.getDrawableForDensity(
+ return dpm.getResources().getDrawableForDensity(
WORK_PROFILE_ICON,
SOLID_COLORED,
context.getResources().getDisplayMetrics().densityDpi,
diff --git a/packages/SettingsLib/src/com/android/settingslib/users/AvatarPhotoController.java b/packages/SettingsLib/src/com/android/settingslib/users/AvatarPhotoController.java
index 0cb2c0b..63a9f0c 100644
--- a/packages/SettingsLib/src/com/android/settingslib/users/AvatarPhotoController.java
+++ b/packages/SettingsLib/src/com/android/settingslib/users/AvatarPhotoController.java
@@ -78,6 +78,11 @@
static final int REQUEST_CODE_TAKE_PHOTO = 1002;
static final int REQUEST_CODE_CROP_PHOTO = 1003;
+ /**
+ * Delay to allow the photo picker exit animation to complete before the crop activity opens.
+ */
+ private static final long DELAY_BEFORE_CROP_MILLIS = 150;
+
private static final String IMAGES_DIR = "multi_user";
private static final String PRE_CROP_PICTURE_FILE_NAME = "PreCropEditUserPhoto.jpg";
private static final String CROP_PICTURE_FILE_NAME = "CropEditUserPhoto.jpg";
@@ -131,13 +136,15 @@
mAvatarUi.returnUriResult(pictureUri);
return true;
case REQUEST_CODE_TAKE_PHOTO:
- case REQUEST_CODE_CHOOSE_PHOTO:
if (mTakePictureUri.equals(pictureUri)) {
cropPhoto(pictureUri);
} else {
- copyAndCropPhoto(pictureUri);
+ copyAndCropPhoto(pictureUri, false);
}
return true;
+ case REQUEST_CODE_CHOOSE_PHOTO:
+ copyAndCropPhoto(pictureUri, true);
+ return true;
}
return false;
}
@@ -154,7 +161,7 @@
mAvatarUi.startActivityForResult(intent, REQUEST_CODE_CHOOSE_PHOTO);
}
- private void copyAndCropPhoto(final Uri pictureUri) {
+ private void copyAndCropPhoto(final Uri pictureUri, boolean delayBeforeCrop) {
try {
ThreadUtils.postOnBackgroundThread(() -> {
final ContentResolver cr = mContextInjector.getContentResolver();
@@ -165,11 +172,17 @@
Log.w(TAG, "Failed to copy photo", e);
return;
}
- ThreadUtils.postOnMainThread(() -> {
+ Runnable cropRunnable = () -> {
if (!mAvatarUi.isFinishing()) {
cropPhoto(mPreCropPictureUri);
}
- });
+ };
+ if (delayBeforeCrop) {
+ ThreadUtils.postOnMainThreadDelayed(cropRunnable, DELAY_BEFORE_CROP_MILLIS);
+ } else {
+ ThreadUtils.postOnMainThread(cropRunnable);
+ }
+
}).get();
} catch (InterruptedException | ExecutionException e) {
Log.e(TAG, "Error performing copy-and-crop", e);
diff --git a/packages/SettingsLib/src/com/android/settingslib/utils/ThreadUtils.java b/packages/SettingsLib/src/com/android/settingslib/utils/ThreadUtils.java
index 69f1c17..2c1d5da 100644
--- a/packages/SettingsLib/src/com/android/settingslib/utils/ThreadUtils.java
+++ b/packages/SettingsLib/src/com/android/settingslib/utils/ThreadUtils.java
@@ -84,6 +84,13 @@
getUiThreadHandler().post(runnable);
}
+ /**
+ * Posts the runnable on the main thread with a delay.
+ */
+ public static void postOnMainThreadDelayed(Runnable runnable, long delayMillis) {
+ getUiThreadHandler().postDelayed(runnable, delayMillis);
+ }
+
private static synchronized ExecutorService getThreadExecutor() {
if (sThreadExecutor == null) {
sThreadExecutor = Executors.newFixedThreadPool(
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/BluetoothEventManagerTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/BluetoothEventManagerTest.java
index 852ac5c..7b94492 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/BluetoothEventManagerTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/BluetoothEventManagerTest.java
@@ -357,7 +357,8 @@
mIntent = new Intent(BluetoothDevice.ACTION_BOND_STATE_CHANGED);
mIntent.putExtra(BluetoothDevice.EXTRA_DEVICE, mBluetoothDevice);
mIntent.putExtra(BluetoothDevice.EXTRA_BOND_STATE, BluetoothDevice.BOND_NONE);
- mIntent.putExtra(BluetoothDevice.EXTRA_REASON, BluetoothDevice.UNBOND_REASON_AUTH_TIMEOUT);
+ mIntent.putExtra(BluetoothDevice.EXTRA_UNBOND_REASON,
+ BluetoothDevice.UNBOND_REASON_AUTH_TIMEOUT);
when(mCachedDeviceManager.findDevice(mBluetoothDevice)).thenReturn(mCachedDevice1);
when(mCachedDevice1.getName()).thenReturn(DEVICE_NAME);
@@ -372,7 +373,7 @@
mIntent = new Intent(BluetoothDevice.ACTION_BOND_STATE_CHANGED);
mIntent.putExtra(BluetoothDevice.EXTRA_DEVICE, mBluetoothDevice);
mIntent.putExtra(BluetoothDevice.EXTRA_BOND_STATE, BluetoothDevice.BOND_NONE);
- mIntent.putExtra(BluetoothDevice.EXTRA_REASON,
+ mIntent.putExtra(BluetoothDevice.EXTRA_UNBOND_REASON,
BluetoothDevice.UNBOND_REASON_REMOTE_DEVICE_DOWN);
when(mCachedDeviceManager.findDevice(mBluetoothDevice)).thenReturn(mCachedDevice1);
when(mCachedDevice1.getName()).thenReturn(DEVICE_NAME);
@@ -388,7 +389,8 @@
mIntent = new Intent(BluetoothDevice.ACTION_BOND_STATE_CHANGED);
mIntent.putExtra(BluetoothDevice.EXTRA_DEVICE, mBluetoothDevice);
mIntent.putExtra(BluetoothDevice.EXTRA_BOND_STATE, BluetoothDevice.BOND_NONE);
- mIntent.putExtra(BluetoothDevice.EXTRA_REASON, BluetoothDevice.UNBOND_REASON_AUTH_REJECTED);
+ mIntent.putExtra(BluetoothDevice.EXTRA_UNBOND_REASON,
+ BluetoothDevice.UNBOND_REASON_AUTH_REJECTED);
when(mCachedDeviceManager.findDevice(mBluetoothDevice)).thenReturn(mCachedDevice1);
when(mCachedDevice1.getName()).thenReturn(DEVICE_NAME);
@@ -403,7 +405,8 @@
mIntent = new Intent(BluetoothDevice.ACTION_BOND_STATE_CHANGED);
mIntent.putExtra(BluetoothDevice.EXTRA_DEVICE, mBluetoothDevice);
mIntent.putExtra(BluetoothDevice.EXTRA_BOND_STATE, BluetoothDevice.BOND_NONE);
- mIntent.putExtra(BluetoothDevice.EXTRA_REASON, BluetoothDevice.UNBOND_REASON_AUTH_FAILED);
+ mIntent.putExtra(BluetoothDevice.EXTRA_UNBOND_REASON,
+ BluetoothDevice.UNBOND_REASON_AUTH_FAILED);
when(mCachedDeviceManager.findDevice(mBluetoothDevice)).thenReturn(mCachedDevice1);
when(mCachedDevice1.getName()).thenReturn(DEVICE_NAME);
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/connectivity/ConnectivitySubsystemsRecoveryManagerTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/connectivity/ConnectivitySubsystemsRecoveryManagerTest.java
new file mode 100644
index 0000000..ca53a18
--- /dev/null
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/connectivity/ConnectivitySubsystemsRecoveryManagerTest.java
@@ -0,0 +1,93 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settingslib.connectivity;
+
+import static org.mockito.Mockito.when;
+
+import android.content.Context;
+import android.content.pm.PackageManager;
+import android.os.Handler;
+
+import androidx.test.core.app.ApplicationProvider;
+
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.Spy;
+import org.mockito.junit.MockitoJUnit;
+import org.mockito.junit.MockitoRule;
+import org.robolectric.RobolectricTestRunner;
+
+@RunWith(RobolectricTestRunner.class)
+public class ConnectivitySubsystemsRecoveryManagerTest {
+
+ @Rule
+ public final MockitoRule mMockitoRule = MockitoJUnit.rule();
+ @Spy
+ Context mContext = ApplicationProvider.getApplicationContext();
+ @Spy
+ Handler mMainHandler = ApplicationProvider.getApplicationContext().getMainThreadHandler();
+ @Mock
+ PackageManager mPackageManager;
+
+ ConnectivitySubsystemsRecoveryManager mConnectivitySubsystemsRecoveryManager;
+
+ @Before
+ public void setUp() {
+ when(mContext.getPackageManager()).thenReturn(mPackageManager);
+ when(mPackageManager.hasSystemFeature(PackageManager.FEATURE_WIFI)).thenReturn(true);
+ when(mPackageManager.hasSystemFeature(PackageManager.FEATURE_TELEPHONY)).thenReturn(true);
+ }
+
+ @Test
+ public void startTrackingWifiRestart_hasNoWifiFeature_shouldNotCrash() {
+ when(mPackageManager.hasSystemFeature(PackageManager.FEATURE_WIFI)).thenReturn(false);
+ mConnectivitySubsystemsRecoveryManager =
+ new ConnectivitySubsystemsRecoveryManager(mContext, mMainHandler);
+
+ mConnectivitySubsystemsRecoveryManager.startTrackingWifiRestart();
+ }
+
+ @Test
+ public void stopTrackingWifiRestart_hasNoWifiFeature_shouldNotCrash() {
+ when(mPackageManager.hasSystemFeature(PackageManager.FEATURE_WIFI)).thenReturn(false);
+ mConnectivitySubsystemsRecoveryManager =
+ new ConnectivitySubsystemsRecoveryManager(mContext, mMainHandler);
+
+ mConnectivitySubsystemsRecoveryManager.stopTrackingWifiRestart();
+ }
+
+ @Test
+ public void startTrackingTelephonyRestart_hasNoTelephonyFeature_shouldNotCrash() {
+ when(mPackageManager.hasSystemFeature(PackageManager.FEATURE_TELEPHONY)).thenReturn(false);
+ mConnectivitySubsystemsRecoveryManager =
+ new ConnectivitySubsystemsRecoveryManager(mContext, mMainHandler);
+
+ mConnectivitySubsystemsRecoveryManager.startTrackingTelephonyRestart();
+ }
+
+ @Test
+ public void stopTrackingTelephonyRestart_hasNoTelephonyFeature_shouldNotCrash() {
+ when(mPackageManager.hasSystemFeature(PackageManager.FEATURE_TELEPHONY)).thenReturn(false);
+ mConnectivitySubsystemsRecoveryManager =
+ new ConnectivitySubsystemsRecoveryManager(mContext, mMainHandler);
+
+ mConnectivitySubsystemsRecoveryManager.stopTrackingTelephonyRestart();
+ }
+}
diff --git a/packages/SettingsProvider/res/values-or/strings.xml b/packages/SettingsProvider/res/values-or/strings.xml
index 486d8ff..85add41 100644
--- a/packages/SettingsProvider/res/values-or/strings.xml
+++ b/packages/SettingsProvider/res/values-or/strings.xml
@@ -19,7 +19,7 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="app_label" msgid="4567566098528588863">"ସେଟିଙ୍ଗ ଷ୍ଟୋରେଜ୍"</string>
+ <string name="app_label" msgid="4567566098528588863">"ସେଟିଂସ ଷ୍ଟୋରେଜ୍"</string>
<string name="wifi_softap_config_change" msgid="5688373762357941645">"ହଟସ୍ପଟ୍ ସେଟିଂସ୍ ବଦଳାଯାଇଛି"</string>
<string name="wifi_softap_config_change_summary" msgid="8946397286141531087">"ବିବରଣୀ ଦେଖିବାକୁ ଟାପ୍ କରନ୍ତୁ"</string>
</resources>
diff --git a/packages/SettingsProvider/test/src/com/android/providers/settings/SettingsProviderTest.java b/packages/SettingsProvider/test/src/com/android/providers/settings/SettingsProviderTest.java
index f49e209..eaf0dcb 100644
--- a/packages/SettingsProvider/test/src/com/android/providers/settings/SettingsProviderTest.java
+++ b/packages/SettingsProvider/test/src/com/android/providers/settings/SettingsProviderTest.java
@@ -188,7 +188,6 @@
int insertedCount = 0;
try {
for (; insertedCount < 1200; insertedCount++) {
- Log.w(LOG_TAG, "Adding app specific setting: " + insertedCount);
insertStringViaProviderApi(SETTING_TYPE_SYSTEM,
String.valueOf(insertedCount), FAKE_SETTING_VALUE, false);
}
@@ -197,7 +196,6 @@
// expected
} finally {
for (; insertedCount >= 0; insertedCount--) {
- Log.w(LOG_TAG, "Removing app specific setting: " + insertedCount);
deleteStringViaProviderApi(SETTING_TYPE_SYSTEM,
String.valueOf(insertedCount));
}
diff --git a/packages/Shell/AndroidManifest.xml b/packages/Shell/AndroidManifest.xml
index e7765e6..955aee9 100644
--- a/packages/Shell/AndroidManifest.xml
+++ b/packages/Shell/AndroidManifest.xml
@@ -122,6 +122,8 @@
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />
<uses-permission android:name="android.permission.BLUETOOTH_ADVERTISE"/>
<uses-permission android:name="android.permission.BLUETOOTH_CONNECT" />
+ <!-- BLUETOOTH_PRIVILEGED is needed for testing purposes only. -->
+ <uses-permission android:name="android.permission.BLUETOOTH_PRIVILEGED" />
<uses-permission android:name="android.permission.BLUETOOTH_SCAN" />
<uses-permission android:name="android.permission.LOCAL_MAC_ADDRESS" />
<uses-permission android:name="android.permission.EXPAND_STATUS_BAR" />
@@ -536,6 +538,7 @@
<uses-permission android:name="android.permission.WIFI_ACCESS_COEX_UNSAFE_CHANNELS" />
<uses-permission android:name="android.permission.WIFI_UPDATE_COEX_UNSAFE_CHANNELS" />
<uses-permission android:name="android.permission.NEARBY_WIFI_DEVICES" />
+ <uses-permission android:name="android.permission.MANAGE_WIFI_INTERFACES" />
<uses-permission android:name="android.permission.OVERRIDE_WIFI_CONFIG" />
<!-- Permission needed for CTS test - ConcurrencyTest#testP2pExternalApprover
P2P external approver API sets require MANAGE_WIFI_NETWORK_SELECTION permission. -->
diff --git a/packages/SystemUI/AndroidManifest.xml b/packages/SystemUI/AndroidManifest.xml
index e24b2d6..4b45cc3 100644
--- a/packages/SystemUI/AndroidManifest.xml
+++ b/packages/SystemUI/AndroidManifest.xml
@@ -314,6 +314,11 @@
<!-- To change system captions state -->
<uses-permission android:name="android.permission.SET_SYSTEM_AUDIO_CAPTION" />
+ <!-- Compat framework -->
+ <uses-permission android:name="android.permission.LOG_COMPAT_CHANGE" />
+ <uses-permission android:name="android.permission.READ_COMPAT_CHANGE_CONFIG" />
+ <uses-permission android:name="android.permission.READ_DEVICE_CONFIG" />
+
<protected-broadcast android:name="com.android.settingslib.action.REGISTER_SLICE_RECEIVER" />
<protected-broadcast android:name="com.android.settingslib.action.UNREGISTER_SLICE_RECEIVER" />
<protected-broadcast android:name="com.android.settings.flashlight.action.FLASHLIGHT_CHANGED" />
diff --git a/packages/SystemUI/TEST_MAPPING b/packages/SystemUI/TEST_MAPPING
index 9722b1f..c8e78c3 100644
--- a/packages/SystemUI/TEST_MAPPING
+++ b/packages/SystemUI/TEST_MAPPING
@@ -180,5 +180,30 @@
}
]
}
+ ],
+ "hubui-presubmit": [
+ {
+ "name": "PlatformScenarioTests",
+ "options": [
+ {
+ "include-annotation": "android.platform.test.annotations.Presubmit"
+ },
+ {
+ "include-annotation": "android.platform.test.scenario.annotation.HubUi"
+ },
+ {
+ "include-filter": "android.platform.test.scenario.hubui"
+ },
+ {
+ "exclude-annotation": "org.junit.Ignore"
+ },
+ {
+ "exclude-annotation": "androidx.test.filters.FlakyTest"
+ },
+ {
+ "exclude-annotation": "android.platform.test.annotations.Postsubmit"
+ }
+ ]
+ }
]
}
diff --git a/packages/SystemUI/res-keyguard/values-it/strings.xml b/packages/SystemUI/res-keyguard/values-it/strings.xml
index 06db7b7..f912a28 100644
--- a/packages/SystemUI/res-keyguard/values-it/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-it/strings.xml
@@ -53,7 +53,7 @@
<string name="kg_wrong_pattern" msgid="5907301342430102842">"Sequenza errata"</string>
<string name="kg_wrong_password" msgid="4143127991071670512">"Password errata"</string>
<string name="kg_wrong_pin" msgid="4160978845968732624">"PIN errato"</string>
- <string name="kg_too_many_failed_attempts_countdown" msgid="2038195171919795529">"{count,plural, =1{Riprova fra # secondo.}one{Riprova fra # secondo.}other{Riprova fra # secondi.}}"</string>
+ <string name="kg_too_many_failed_attempts_countdown" msgid="2038195171919795529">"{count,plural, =1{Riprova fra # secondo.}other{Riprova fra # secondi.}}"</string>
<string name="kg_sim_pin_instructions" msgid="1942424305184242951">"Inserisci il PIN della SIM."</string>
<string name="kg_sim_pin_instructions_multi" msgid="3639863309953109649">"Inserisci il PIN della SIM \"<xliff:g id="CARRIER">%1$s</xliff:g>\"."</string>
<string name="kg_sim_lock_esim_instructions" msgid="5577169988158738030">"<xliff:g id="PREVIOUS_MSG">%1$s</xliff:g> Disattiva la eSIM per usare il dispositivo senza servizio dati mobile."</string>
@@ -69,13 +69,13 @@
<string name="kg_too_many_failed_pattern_attempts_dialog_message" msgid="4252405904570284368">"<xliff:g id="NUMBER_0">%1$d</xliff:g> tentativi errati di inserimento della sequenza di sblocco. \n\nRiprova tra <xliff:g id="NUMBER_1">%2$d</xliff:g> secondi."</string>
<string name="kg_password_wrong_pin_code_pukked" msgid="8047350661459040581">"Codice PIN della SIM errato. Devi contattare l\'operatore per sbloccare il dispositivo."</string>
<plurals name="kg_password_wrong_pin_code" formatted="false" msgid="7030584350995485026">
- <item quantity="one">Incorrect SIM PIN code, you have <xliff:g id="NUMBER_1">%d</xliff:g> remaining attempts.</item>
<item quantity="other">Codice PIN della SIM errato. Hai ancora <xliff:g id="NUMBER_1">%d</xliff:g> tentativi a disposizione.</item>
+ <item quantity="one">Codice PIN della SIM errato. Hai ancora <xliff:g id="NUMBER_0">%d</xliff:g> tentativo a disposizione, dopodiché dovrai contattare l\'operatore per sbloccare il dispositivo.</item>
</plurals>
<string name="kg_password_wrong_puk_code_dead" msgid="3698285357028468617">"SIM inutilizzabile. Contatta il tuo operatore."</string>
<plurals name="kg_password_wrong_puk_code" formatted="false" msgid="3937306685604862886">
- <item quantity="one">Incorrect SIM PUK code, you have <xliff:g id="NUMBER_1">%d</xliff:g> remaining attempts before SIM becomes permanently unusable.</item>
<item quantity="other">Codice PUK della SIM errato. Hai ancora <xliff:g id="NUMBER_1">%d</xliff:g> tentativi a disposizione prima che la SIM diventi definitivamente inutilizzabile.</item>
+ <item quantity="one">Codice PUK della SIM errato. Hai ancora <xliff:g id="NUMBER_0">%d</xliff:g> tentativo a disposizione prima che la SIM diventi definitivamente inutilizzabile.</item>
</plurals>
<string name="kg_password_pin_failed" msgid="5136259126330604009">"Operazione con PIN della SIM non riuscita."</string>
<string name="kg_password_puk_failed" msgid="6778867411556937118">"Operazione con PUK della SIM non riuscita."</string>
@@ -92,12 +92,12 @@
<string name="kg_face_not_recognized" msgid="7903950626744419160">"Non riconosciuto"</string>
<string name="kg_face_sensor_privacy_enabled" msgid="6513157891227284806">"Per utilizzare lo sblocco con il volto, attiva "<b>"l\'accesso alla fotocamera"</b>" in Impostazioni > Privacy"</string>
<plurals name="kg_password_default_pin_message" formatted="false" msgid="7730152526369857818">
- <item quantity="one">Enter SIM PIN. You have <xliff:g id="NUMBER_1">%d</xliff:g> remaining attempts.</item>
<item quantity="other">Inserisci il codice PIN della SIM. Hai ancora <xliff:g id="NUMBER_1">%d</xliff:g> tentativi a disposizione.</item>
+ <item quantity="one">Inserisci il codice PIN della SIM. Hai ancora <xliff:g id="NUMBER_0">%d</xliff:g> tentativo a disposizione, dopodiché dovrai contattare l\'operatore per sbloccare il dispositivo.</item>
</plurals>
<plurals name="kg_password_default_puk_message" formatted="false" msgid="571308542462946935">
- <item quantity="one">SIM is now disabled. Enter PUK code to continue. You have <xliff:g id="_NUMBER_1">%d</xliff:g> remaining attempts before SIM becomes permanently unusable. Contact carrier for details.</item>
<item quantity="other">La scheda SIM è ora disattivata. Inserisci il codice PUK per continuare. Hai ancora <xliff:g id="_NUMBER_1">%d</xliff:g> tentativi a disposizione prima che la SIM diventi definitivamente inutilizzabile. Per informazioni dettagliate, contatta l\'operatore.</item>
+ <item quantity="one">La scheda SIM è ora disattivata. Inserisci il codice PUK per continuare. Hai ancora <xliff:g id="_NUMBER_0">%d</xliff:g> tentativo a disposizione prima che la SIM diventi definitivamente inutilizzabile. Per informazioni dettagliate, contatta l\'operatore.</item>
</plurals>
<string name="clock_title_default" msgid="6342735240617459864">"Predefinito"</string>
<string name="clock_title_bubble" msgid="2204559396790593213">"Bolla"</string>
diff --git a/packages/SystemUI/res-keyguard/values-pt-rPT/strings.xml b/packages/SystemUI/res-keyguard/values-pt-rPT/strings.xml
index c3486bb..a8d8f34 100644
--- a/packages/SystemUI/res-keyguard/values-pt-rPT/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-pt-rPT/strings.xml
@@ -53,7 +53,7 @@
<string name="kg_wrong_pattern" msgid="5907301342430102842">"Padrão incorreto."</string>
<string name="kg_wrong_password" msgid="4143127991071670512">"Palavra-passe incorreta."</string>
<string name="kg_wrong_pin" msgid="4160978845968732624">"PIN incorreto"</string>
- <string name="kg_too_many_failed_attempts_countdown" msgid="2038195171919795529">"{count,plural, =1{Tente novamente dentro de # segundo.}one{Tente novamente dentro de # segundo(s).}other{Tente novamente dentro de # segundos.}}"</string>
+ <string name="kg_too_many_failed_attempts_countdown" msgid="2038195171919795529">"{count,plural, =1{Tente novamente dentro de # segundo.}other{Tente novamente dentro de # segundos.}}"</string>
<string name="kg_sim_pin_instructions" msgid="1942424305184242951">"Introduza o PIN do cartão SIM."</string>
<string name="kg_sim_pin_instructions_multi" msgid="3639863309953109649">"Introduza o PIN do cartão SIM \"<xliff:g id="CARRIER">%1$s</xliff:g>\"."</string>
<string name="kg_sim_lock_esim_instructions" msgid="5577169988158738030">"<xliff:g id="PREVIOUS_MSG">%1$s</xliff:g> Desative o eSIM para utilizar o dispositivo sem serviço móvel."</string>
@@ -69,13 +69,13 @@
<string name="kg_too_many_failed_pattern_attempts_dialog_message" msgid="4252405904570284368">"Desenhou a sua padrão de desbloqueio incorretamente <xliff:g id="NUMBER_0">%1$d</xliff:g> vezes. \n\nTente novamente dentro de <xliff:g id="NUMBER_1">%2$d</xliff:g> segundos."</string>
<string name="kg_password_wrong_pin_code_pukked" msgid="8047350661459040581">"Código PIN do cartão SIM incorreto. Tem de contactar o seu operador para desbloquear o dispositivo."</string>
<plurals name="kg_password_wrong_pin_code" formatted="false" msgid="7030584350995485026">
- <item quantity="one">Código PIN do cartão SIM incorreto. Tem mais <xliff:g id="NUMBER_0">%d</xliff:g> tentativa antes de precisar de contactar o seu operador para desbloquear o dispositivo.</item>
<item quantity="other">Código PIN do cartão SIM incorreto. Tem mais <xliff:g id="NUMBER_1">%d</xliff:g> tentativas.</item>
+ <item quantity="one">Código PIN do cartão SIM incorreto. Tem mais <xliff:g id="NUMBER_0">%d</xliff:g> tentativa antes de precisar de contactar o seu operador para desbloquear o dispositivo.</item>
</plurals>
<string name="kg_password_wrong_puk_code_dead" msgid="3698285357028468617">"Cartão SIM inutilizável. Contacte o seu operador."</string>
<plurals name="kg_password_wrong_puk_code" formatted="false" msgid="3937306685604862886">
- <item quantity="one">Código PUK do cartão SIM incorreto. Tem mais <xliff:g id="NUMBER_0">%d</xliff:g> tentativa antes de o cartão SIM ficar permanentemente inutilizável.</item>
<item quantity="other">Código PUK do cartão SIM incorreto. Tem mais <xliff:g id="NUMBER_1">%d</xliff:g> tentativas antes de o cartão SIM ficar permanentemente inutilizável.</item>
+ <item quantity="one">Código PUK do cartão SIM incorreto. Tem mais <xliff:g id="NUMBER_0">%d</xliff:g> tentativa antes de o cartão SIM ficar permanentemente inutilizável.</item>
</plurals>
<string name="kg_password_pin_failed" msgid="5136259126330604009">"Falha ao introduzir o PIN do cartão SIM!"</string>
<string name="kg_password_puk_failed" msgid="6778867411556937118">"Falha ao introduzir o PUK do cartão SIM!"</string>
@@ -92,12 +92,12 @@
<string name="kg_face_not_recognized" msgid="7903950626744419160">"Não reconhecido."</string>
<string name="kg_face_sensor_privacy_enabled" msgid="6513157891227284806">"Para utilizar o Desbloqueio facial, ative o "<b>"Acesso à câmara"</b>" em Definições > Privacidade"</string>
<plurals name="kg_password_default_pin_message" formatted="false" msgid="7730152526369857818">
- <item quantity="one">Introduza o PIN do cartão SIM. Tem mais <xliff:g id="NUMBER_0">%d</xliff:g> tentativa antes de ser necessário contactar o operador para desbloquear o dispositivo.</item>
<item quantity="other">Introduza o PIN do cartão SIM. Tem mais <xliff:g id="NUMBER_1">%d</xliff:g> tentativas.</item>
+ <item quantity="one">Introduza o PIN do cartão SIM. Tem mais <xliff:g id="NUMBER_0">%d</xliff:g> tentativa antes de ser necessário contactar o operador para desbloquear o dispositivo.</item>
</plurals>
<plurals name="kg_password_default_puk_message" formatted="false" msgid="571308542462946935">
- <item quantity="one">O SIM encontra-se desativado. Introduza o código PUK para continuar. Tem mais <xliff:g id="_NUMBER_0">%d</xliff:g> tentativa antes de o cartão SIM ficar permanentemente inutilizável. Contacte o operador para obter mais detalhes.</item>
<item quantity="other">O SIM encontra-se desativado. Introduza o código PUK para continuar. Tem mais <xliff:g id="_NUMBER_1">%d</xliff:g> tentativas antes de o cartão SIM ficar permanentemente inutilizável. Contacte o operador para obter mais detalhes.</item>
+ <item quantity="one">O SIM encontra-se desativado. Introduza o código PUK para continuar. Tem mais <xliff:g id="_NUMBER_0">%d</xliff:g> tentativa antes de o cartão SIM ficar permanentemente inutilizável. Contacte o operador para obter mais detalhes.</item>
</plurals>
<string name="clock_title_default" msgid="6342735240617459864">"Predefinido"</string>
<string name="clock_title_bubble" msgid="2204559396790593213">"Balão"</string>
diff --git a/packages/SystemUI/res-keyguard/values/dimens.xml b/packages/SystemUI/res-keyguard/values/dimens.xml
index 8d205c1..9a6f5ed 100644
--- a/packages/SystemUI/res-keyguard/values/dimens.xml
+++ b/packages/SystemUI/res-keyguard/values/dimens.xml
@@ -129,4 +129,7 @@
<dimen name="user_switcher_icon_selected_width">8dp</dimen>
<dimen name="user_switcher_fullscreen_button_text_size">14sp</dimen>
<dimen name="user_switcher_fullscreen_button_padding">12dp</dimen>
+
+ <!-- Translation y for appear animation -->
+ <dimen name="keyguard_host_view_translation_y">80dp</dimen>
</resources>
diff --git a/packages/SystemUI/res/drawable/ic_circular_unchecked.xml b/packages/SystemUI/res/drawable/ic_circular_unchecked.xml
index 9b43cf6..779ab81 100644
--- a/packages/SystemUI/res/drawable/ic_circular_unchecked.xml
+++ b/packages/SystemUI/res/drawable/ic_circular_unchecked.xml
@@ -4,6 +4,6 @@
android:viewportWidth="24"
android:viewportHeight="24">
<path
- android:fillColor="@color/media_dialog_inactive_item_main_content"
+ android:fillColor="@color/media_dialog_item_main_content"
android:pathData="M12,22q-2.075,0 -3.9,-0.788 -1.825,-0.787 -3.175,-2.137 -1.35,-1.35 -2.137,-3.175Q2,14.075 2,12t0.788,-3.9q0.787,-1.825 2.137,-3.175 1.35,-1.35 3.175,-2.137Q9.925,2 12,2t3.9,0.788q1.825,0.787 3.175,2.137 1.35,1.35 2.137,3.175Q22,9.925 22,12t-0.788,3.9q-0.787,1.825 -2.137,3.175 -1.35,1.35 -3.175,2.137Q14.075,22 12,22zM12,12zM12,20q3.325,0 5.663,-2.337Q20,15.325 20,12t-2.337,-5.662Q15.325,4 12,4T6.338,6.338Q4,8.675 4,12q0,3.325 2.338,5.663Q8.675,20 12,20z"/>
</vector>
diff --git a/packages/SystemUI/res/drawable/media_output_status_check.xml b/packages/SystemUI/res/drawable/media_output_status_check.xml
index 1b750f8..5fbc42b 100644
--- a/packages/SystemUI/res/drawable/media_output_status_check.xml
+++ b/packages/SystemUI/res/drawable/media_output_status_check.xml
@@ -21,6 +21,6 @@
android:viewportHeight="24"
android:tint="?attr/colorControlNormal">
<path
- android:fillColor="@color/media_dialog_item_status"
+ android:fillColor="@color/media_dialog_item_main_content"
android:pathData="M9,16.2L4.8,12l-1.4,1.4L9,19 21,7l-1.4,-1.4L9,16.2z"/>
</vector>
diff --git a/packages/SystemUI/res/drawable/media_output_status_failed.xml b/packages/SystemUI/res/drawable/media_output_status_failed.xml
index 05c6358..0599e23 100644
--- a/packages/SystemUI/res/drawable/media_output_status_failed.xml
+++ b/packages/SystemUI/res/drawable/media_output_status_failed.xml
@@ -21,6 +21,6 @@
android:viewportHeight="24"
android:tint="?attr/colorControlNormal">
<path
- android:fillColor="@color/media_dialog_inactive_item_main_content"
+ android:fillColor="@color/media_dialog_item_main_content"
android:pathData="M11,7h2v2h-2zM11,11h2v6h-2zM12,2C6.48,2 2,6.48 2,12s4.48,10 10,10 10,-4.48 10,-10S17.52,2 12,2zM12,20c-4.41,0 -8,-3.59 -8,-8s3.59,-8 8,-8 8,3.59 8,8 -3.59,8 -8,8z"/>
</vector>
diff --git a/packages/SystemUI/res/drawable/media_ttt_undo_background.xml b/packages/SystemUI/res/drawable/media_ttt_undo_background.xml
index ec74ee1..3e2e4f0 100644
--- a/packages/SystemUI/res/drawable/media_ttt_undo_background.xml
+++ b/packages/SystemUI/res/drawable/media_ttt_undo_background.xml
@@ -14,9 +14,14 @@
~ See the License for the specific language governing permissions and
~ limitations under the License.
-->
-<shape
+<ripple
xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:androidprv="http://schemas.android.com/apk/prv/res/android">
- <solid android:color="?androidprv:attr/colorAccentPrimary" />
- <corners android:radius="24dp" />
-</shape>
+ xmlns:androidprv="http://schemas.android.com/apk/prv/res/android"
+ android:color="?android:textColorPrimary">
+ <item android:id="@android:id/background">
+ <shape>
+ <solid android:color="?androidprv:attr/colorAccentPrimary"/>
+ <corners android:radius="24dp" />
+ </shape>
+ </item>
+</ripple>
diff --git a/packages/SystemUI/res/drawable/user_switcher_icon_large.xml b/packages/SystemUI/res/drawable/user_switcher_icon_large.xml
index 1ed7553..d81b518 100644
--- a/packages/SystemUI/res/drawable/user_switcher_icon_large.xml
+++ b/packages/SystemUI/res/drawable/user_switcher_icon_large.xml
@@ -27,7 +27,7 @@
</shape>
</item>
<!-- When an item is selected, this layer will show a ring around the icon -->
- <item>
+ <item android:id="@+id/ring">
<shape android:shape="oval">
<stroke
android:width="@dimen/user_switcher_icon_selected_width"
@@ -35,7 +35,7 @@
</shape>
</item>
<!-- Where the user drawable/bitmap will be placed -->
- <item
+ <item android:id="@+id/user_avatar"
android:drawable="@drawable/user_avatar_bg"
android:width="@dimen/bouncer_user_switcher_icon_size"
android:height="@dimen/bouncer_user_switcher_icon_size"
diff --git a/packages/SystemUI/res/layout/dream_overlay_complication_clock_date.xml b/packages/SystemUI/res/layout/dream_overlay_complication_clock_date.xml
index 91d81a2..cb63300 100644
--- a/packages/SystemUI/res/layout/dream_overlay_complication_clock_date.xml
+++ b/packages/SystemUI/res/layout/dream_overlay_complication_clock_date.xml
@@ -19,6 +19,7 @@
android:id="@+id/date_view"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
+ android:paddingHorizontal="@dimen/dream_overlay_complication_shadow_padding"
android:gravity="center_horizontal"
android:textColor="@android:color/white"
android:shadowColor="@color/keyguard_shadow_color"
diff --git a/packages/SystemUI/res/layout/dream_overlay_complication_weather.xml b/packages/SystemUI/res/layout/dream_overlay_complication_weather.xml
index 3900ea5..76fe58c 100644
--- a/packages/SystemUI/res/layout/dream_overlay_complication_weather.xml
+++ b/packages/SystemUI/res/layout/dream_overlay_complication_weather.xml
@@ -19,6 +19,7 @@
android:id="@+id/weather_view"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
+ android:paddingHorizontal="@dimen/dream_overlay_complication_shadow_padding"
android:textColor="@android:color/white"
android:shadowColor="@color/keyguard_shadow_color"
android:shadowRadius="?attr/shadowRadius"
diff --git a/packages/SystemUI/res/layout/media_output_list_item.xml b/packages/SystemUI/res/layout/media_output_list_item.xml
index eeb37c7..20747fa 100644
--- a/packages/SystemUI/res/layout/media_output_list_item.xml
+++ b/packages/SystemUI/res/layout/media_output_list_item.xml
@@ -83,7 +83,7 @@
android:ellipsize="end"
android:maxLines="1"
android:fontFamily="@*android:string/config_headlineFontFamilyMedium"
- android:textColor="@color/media_dialog_inactive_item_main_content"
+ android:textColor="@color/media_dialog_item_main_content"
android:textSize="16sp"/>
<TextView
android:id="@+id/subtitle"
@@ -91,7 +91,7 @@
android:layout_height="wrap_content"
android:ellipsize="end"
android:maxLines="1"
- android:textColor="@color/media_dialog_inactive_item_main_content"
+ android:textColor="@color/media_dialog_item_main_content"
android:textSize="14sp"
android:fontFamily="@*android:string/config_bodyFontFamily"
android:visibility="gone"/>
diff --git a/packages/SystemUI/res/layout/ongoing_privacy_chip.xml b/packages/SystemUI/res/layout/ongoing_privacy_chip.xml
index ad2bc79..5aa6080 100644
--- a/packages/SystemUI/res/layout/ongoing_privacy_chip.xml
+++ b/packages/SystemUI/res/layout/ongoing_privacy_chip.xml
@@ -37,7 +37,5 @@
android:layout_gravity="center"
android:minWidth="@dimen/ongoing_appops_chip_min_width"
android:maxWidth="@dimen/ongoing_appops_chip_max_width"
- android:clipChildren="false"
- android:clipToPadding="false"
/>
</com.android.systemui.privacy.OngoingPrivacyChip>
\ No newline at end of file
diff --git a/packages/SystemUI/res/values-af/strings.xml b/packages/SystemUI/res/values-af/strings.xml
index c0fdf68..8d09d76 100644
--- a/packages/SystemUI/res/values-af/strings.xml
+++ b/packages/SystemUI/res/values-af/strings.xml
@@ -20,19 +20,17 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_label" msgid="4811759950673118541">"Stelsel-UI"</string>
- <!-- no translation found for battery_low_title (5319680173344341779) -->
- <skip />
- <!-- no translation found for battery_low_description (3282977755476423966) -->
- <skip />
- <!-- no translation found for battery_low_intro (5148725009653088790) -->
- <skip />
+ <string name="battery_low_title" msgid="5319680173344341779">"Skakel Batterybespaarder aan?"</string>
+ <string name="battery_low_description" msgid="3282977755476423966">"Jy het <xliff:g id="PERCENTAGE">%s</xliff:g> batterykrag oor. Batterybespaarder skakel Donkertema aan, beperk agtergrondaktiwiteit en vertraag kennisgewings."</string>
+ <string name="battery_low_intro" msgid="5148725009653088790">"Batterybespaarder skakel Donkertema aan, beperk agtergrondaktiwiteit en vertraag kennisgewings."</string>
<string name="battery_low_percent_format" msgid="4276661262843170964">"<xliff:g id="PERCENTAGE">%s</xliff:g> oor"</string>
<string name="invalid_charger_title" msgid="938685362320735167">"Kan nie deur USB laai nie"</string>
<string name="invalid_charger_text" msgid="2339310107232691577">"Gebruik die laaier wat jy saam met jou toestel gekry het"</string>
<string name="battery_saver_confirmation_title" msgid="1234998463717398453">"Skakel Batterybespaarder aan?"</string>
<string name="battery_saver_confirmation_title_generic" msgid="2299231884234959849">"Meer oor Batterybespaarder"</string>
<string name="battery_saver_confirmation_ok" msgid="5042136476802816494">"Skakel aan"</string>
- <string name="battery_saver_start_action" msgid="4553256017945469937">"Skakel Batterybespaarder aan"</string>
+ <string name="battery_saver_start_action" msgid="8353766979886287140">"Skakel aan"</string>
+ <string name="battery_saver_dismiss_action" msgid="7199342621040014738">"Nee, dankie"</string>
<string name="status_bar_settings_auto_rotation" msgid="8329080442278431708">"Outodraai skerm"</string>
<string name="usb_device_permission_prompt" msgid="4414719028369181772">"Gee <xliff:g id="APPLICATION">%1$s</xliff:g> toegang tot <xliff:g id="USB_DEVICE">%2$s</xliff:g>?"</string>
<string name="usb_device_permission_prompt_warn" msgid="2309129784984063656">"Laat <xliff:g id="APPLICATION">%1$s</xliff:g> toe om by <xliff:g id="USB_DEVICE">%2$s</xliff:g> in te gaan?\nOpneemtoestemming is nie aan hierdie program verleen nie, maar dit kan oudio deur hierdie USB-toestel vasvang."</string>
@@ -133,8 +131,7 @@
<string name="biometric_dialog_face_icon_description_authenticated" msgid="2242167416140740920">"Gesig is gestaaf"</string>
<string name="biometric_dialog_face_icon_description_confirmed" msgid="7918067993953940778">"Bevestig"</string>
<string name="biometric_dialog_tap_confirm" msgid="9166350738859143358">"Tik op Bevestig om te voltooi"</string>
- <!-- no translation found for biometric_dialog_tap_confirm_with_face (1597899891472340950) -->
- <skip />
+ <string name="biometric_dialog_tap_confirm_with_face" msgid="1597899891472340950">"Ontsluit met jou gesig. Druk om voort te gaan."</string>
<string name="biometric_dialog_authenticated" msgid="7337147327545272484">"Gestaaf"</string>
<string name="biometric_dialog_use_pin" msgid="8385294115283000709">"Gebruik PIN"</string>
<string name="biometric_dialog_use_pattern" msgid="2315593393167211194">"Gebruik patroon"</string>
@@ -462,8 +459,8 @@
<string name="wallet_secondary_label_device_locked" msgid="5175862019125370506">"Ontsluit om te gebruik"</string>
<string name="wallet_error_generic" msgid="257704570182963611">"Kon nie jou kaarte kry nie; probeer later weer"</string>
<string name="wallet_lockscreen_settings_label" msgid="3539105300870383570">"Sluitskerminstellings"</string>
- <string name="qr_code_scanner_title" msgid="5660820608548306581">"QR-kode"</string>
- <string name="qr_code_scanner_description" msgid="7937603775306661863">"Tik om te skandeer"</string>
+ <!-- no translation found for qr_code_scanner_title (5290201053875420785) -->
+ <skip />
<string name="status_bar_work" msgid="5238641949837091056">"Werkprofiel"</string>
<string name="status_bar_airplane" msgid="4848702508684541009">"Vliegtuigmodus"</string>
<string name="zen_alarm_warning" msgid="7844303238486849503">"Jy sal nie jou volgende wekker <xliff:g id="WHEN">%1$s</xliff:g> hoor nie"</string>
@@ -827,6 +824,7 @@
<string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"Bind nuwe toestel saam"</string>
<string name="media_output_dialog_launch_app_text" msgid="1527413319632586259">"Maak die program oop om hierdie sessie uit te saai."</string>
<string name="media_output_dialog_unknown_launch_app_name" msgid="1084899329829371336">"Onbekende program"</string>
+ <string name="media_output_dialog_button_stop_casting" msgid="6581379537930199189">"Hou op uitsaai"</string>
<string name="build_number_clip_data_label" msgid="3623176728412560914">"Bounommer"</string>
<string name="build_number_copy_toast" msgid="877720921605503046">"Bounommer is na knipbord gekopieer."</string>
<string name="basic_status" msgid="2315371112182658176">"Maak gesprek oop"</string>
@@ -916,8 +914,6 @@
<string name="dream_overlay_status_bar_wifi_off" msgid="4497069245055003582">"Wi‑fi onbeskikbaar"</string>
<string name="dream_overlay_status_bar_priority_mode" msgid="5428462123314728739">"Prioriteitmodus"</string>
<string name="dream_overlay_status_bar_alarm_set" msgid="566707328356590886">"Wekker gestel"</string>
- <string name="dream_overlay_status_bar_assistant_guest_mode_enabled" msgid="3715897096012469615">"Assistent-gasmodus is geaktiveer"</string>
<string name="dream_overlay_status_bar_camera_mic_off" msgid="3199425257833773569">"Kamera en mikrofoon is af"</string>
- <!-- no translation found for dream_overlay_status_bar_notification_indicator (8091389255691081711) -->
- <skip />
+ <string name="dream_overlay_status_bar_notification_indicator" msgid="8091389255691081711">"{count,plural, =1{# kennisgewing}other{# kennisgewings}}"</string>
</resources>
diff --git a/packages/SystemUI/res/values-am/strings.xml b/packages/SystemUI/res/values-am/strings.xml
index 43ad005..83c0184 100644
--- a/packages/SystemUI/res/values-am/strings.xml
+++ b/packages/SystemUI/res/values-am/strings.xml
@@ -20,19 +20,17 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_label" msgid="4811759950673118541">"የስርዓት UI"</string>
- <!-- no translation found for battery_low_title (5319680173344341779) -->
- <skip />
- <!-- no translation found for battery_low_description (3282977755476423966) -->
- <skip />
- <!-- no translation found for battery_low_intro (5148725009653088790) -->
- <skip />
+ <string name="battery_low_title" msgid="5319680173344341779">"ባትሪ ቆጣቢ ይብራ?"</string>
+ <string name="battery_low_description" msgid="3282977755476423966">"<xliff:g id="PERCENTAGE">%s</xliff:g> ቀሪ ባትሪ አለዎት። የባትሪ ኃይል ቆጣቢ ጠቆር ያለ ገጽታ ያበራል፣ የበስተጀርባ እንቅስቃሴን ይገድባል እና ማሳወቂያዎችን ያዘገያል።"</string>
+ <string name="battery_low_intro" msgid="5148725009653088790">"የባትሪ ኃይል ቆጣቢ ጠቆር ያለ ገጽታ ያበራል፣ የበስተጀርባ እንቅስቃሴን ይገድባል እና ማሳወቂያዎችን ያዘገያል።"</string>
<string name="battery_low_percent_format" msgid="4276661262843170964">"<xliff:g id="PERCENTAGE">%s</xliff:g> ይቀራል"</string>
<string name="invalid_charger_title" msgid="938685362320735167">"በዩኤስቢ በኩል ኃይል መሙላት አይቻልም"</string>
<string name="invalid_charger_text" msgid="2339310107232691577">"ከእርስዎ መሣሪያ ጋር የመጣውን ኃይል መሙያ ይጠቀሙ"</string>
<string name="battery_saver_confirmation_title" msgid="1234998463717398453">"ባትሪ ቆጣቢ ይብራ?"</string>
<string name="battery_saver_confirmation_title_generic" msgid="2299231884234959849">"ስለ ባትሪ ቆጣቢ"</string>
<string name="battery_saver_confirmation_ok" msgid="5042136476802816494">"አብራ"</string>
- <string name="battery_saver_start_action" msgid="4553256017945469937">"ባትሪ ቆጣቢን አብራ"</string>
+ <string name="battery_saver_start_action" msgid="8353766979886287140">"አብራ"</string>
+ <string name="battery_saver_dismiss_action" msgid="7199342621040014738">"አይ፣ አመሰግናለሁ"</string>
<string name="status_bar_settings_auto_rotation" msgid="8329080442278431708">"ማያ በራስ ሰር አሽከርክር"</string>
<string name="usb_device_permission_prompt" msgid="4414719028369181772">"<xliff:g id="APPLICATION">%1$s</xliff:g> <xliff:g id="USB_DEVICE">%2$s</xliff:g>ን እንዲደርስበት ይፈቀድለት?"</string>
<string name="usb_device_permission_prompt_warn" msgid="2309129784984063656">"<xliff:g id="APPLICATION">%1$s</xliff:g> <xliff:g id="USB_DEVICE">%2$s</xliff:g>ን እንዲደርስ ይፈቀድለት?\nይህ መተግበሪያ የመቅዳት ፈቃድ አልተሰጠውም፣ ነገር ግን በዩኤስቢ መሣሪያ በኩል ኦዲዮን መቅዳት ይችላል።"</string>
@@ -133,8 +131,7 @@
<string name="biometric_dialog_face_icon_description_authenticated" msgid="2242167416140740920">"መልክ ተረጋግጧል"</string>
<string name="biometric_dialog_face_icon_description_confirmed" msgid="7918067993953940778">"ተረጋግጧል"</string>
<string name="biometric_dialog_tap_confirm" msgid="9166350738859143358">"ለማጠናቀቅ አረጋግጥን መታ ያድርጉ"</string>
- <!-- no translation found for biometric_dialog_tap_confirm_with_face (1597899891472340950) -->
- <skip />
+ <string name="biometric_dialog_tap_confirm_with_face" msgid="1597899891472340950">"በፊትዎ የተከፈተ። ለመቀጠል ይጫኑ።"</string>
<string name="biometric_dialog_authenticated" msgid="7337147327545272484">"የተረጋገጠ"</string>
<string name="biometric_dialog_use_pin" msgid="8385294115283000709">"ፒን ይጠቀሙ"</string>
<string name="biometric_dialog_use_pattern" msgid="2315593393167211194">"ሥርዓተ ጥለትን ተጠቀም"</string>
@@ -462,8 +459,8 @@
<string name="wallet_secondary_label_device_locked" msgid="5175862019125370506">"ለማየት ይክፈቱ"</string>
<string name="wallet_error_generic" msgid="257704570182963611">"የእርስዎን ካርዶች ማግኘት ላይ ችግር ነበር፣ እባክዎ ቆይተው እንደገና ይሞክሩ"</string>
<string name="wallet_lockscreen_settings_label" msgid="3539105300870383570">"የገጽ መቆለፊያ ቅንብሮች"</string>
- <string name="qr_code_scanner_title" msgid="5660820608548306581">"QR ኮድ"</string>
- <string name="qr_code_scanner_description" msgid="7937603775306661863">"ለመቃኘት መታ ያድርጉ"</string>
+ <!-- no translation found for qr_code_scanner_title (5290201053875420785) -->
+ <skip />
<string name="status_bar_work" msgid="5238641949837091056">"የስራ መገለጫ"</string>
<string name="status_bar_airplane" msgid="4848702508684541009">"የአውሮፕላን ሁነታ"</string>
<string name="zen_alarm_warning" msgid="7844303238486849503">"የእርስዎን ቀጣይ ማንቂያ <xliff:g id="WHEN">%1$s</xliff:g> አይሰሙም"</string>
@@ -827,6 +824,7 @@
<string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"አዲስ መሣሪያ ያጣምሩ"</string>
<string name="media_output_dialog_launch_app_text" msgid="1527413319632586259">"ይህን ክፍለ ጊዜ cast ለማድረግ፣ እባክዎ መተግበሪያውን ይክፈቱ።"</string>
<string name="media_output_dialog_unknown_launch_app_name" msgid="1084899329829371336">"የማይታወቅ መተግበሪያ"</string>
+ <string name="media_output_dialog_button_stop_casting" msgid="6581379537930199189">"Cast ማድረግ አቁም"</string>
<string name="build_number_clip_data_label" msgid="3623176728412560914">"የግንብ ቁጥር"</string>
<string name="build_number_copy_toast" msgid="877720921605503046">"የገንባ ቁጥር ወደ ቅንጥብ ሰሌዳ ተቀድቷል።"</string>
<string name="basic_status" msgid="2315371112182658176">"ውይይት ይክፈቱ"</string>
@@ -916,8 +914,6 @@
<string name="dream_overlay_status_bar_wifi_off" msgid="4497069245055003582">"Wi‑Fi አይገኝም"</string>
<string name="dream_overlay_status_bar_priority_mode" msgid="5428462123314728739">"የቅድሚያ ሁነታ"</string>
<string name="dream_overlay_status_bar_alarm_set" msgid="566707328356590886">"ማንቂያ ተቀናብሯል"</string>
- <string name="dream_overlay_status_bar_assistant_guest_mode_enabled" msgid="3715897096012469615">"የረዳት እንግዳ ሁነታ ነቅቷል"</string>
<string name="dream_overlay_status_bar_camera_mic_off" msgid="3199425257833773569">"ካሜራ እና ማይክሮፎን ጠፍተዋል"</string>
- <!-- no translation found for dream_overlay_status_bar_notification_indicator (8091389255691081711) -->
- <skip />
+ <string name="dream_overlay_status_bar_notification_indicator" msgid="8091389255691081711">"{count,plural, =1{# ማሳወቂያ}one{# ማሳወቂያዎች}other{# ማሳወቂያዎች}}"</string>
</resources>
diff --git a/packages/SystemUI/res/values-ar/strings.xml b/packages/SystemUI/res/values-ar/strings.xml
index 5ec5e9b..24e36fb 100644
--- a/packages/SystemUI/res/values-ar/strings.xml
+++ b/packages/SystemUI/res/values-ar/strings.xml
@@ -20,19 +20,17 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_label" msgid="4811759950673118541">"واجهة مستخدم النظام"</string>
- <!-- no translation found for battery_low_title (5319680173344341779) -->
- <skip />
- <!-- no translation found for battery_low_description (3282977755476423966) -->
- <skip />
- <!-- no translation found for battery_low_intro (5148725009653088790) -->
- <skip />
+ <string name="battery_low_title" msgid="5319680173344341779">"هل تريد تفعيل ميزة \"توفير شحن البطارية\"؟"</string>
+ <string name="battery_low_description" msgid="3282977755476423966">"يتبقى لديك <xliff:g id="PERCENTAGE">%s</xliff:g> من شحن البطارية. يؤدي استخدام ميزة \"توفير شحن البطارية\" إلى تفعيل وضع \"المظهر الداكن\" وتقييد الأنشطة في الخلفية وتأخير الإشعارات."</string>
+ <string name="battery_low_intro" msgid="5148725009653088790">"يؤدي استخدام ميزة \"توفير شحن البطارية\" إلى تفعيل وضع \"المظهر الداكن\" وتقييد الأنشطة في الخلفية وتأخير الإشعارات."</string>
<string name="battery_low_percent_format" msgid="4276661262843170964">"متبقي <xliff:g id="PERCENTAGE">%s</xliff:g>"</string>
<string name="invalid_charger_title" msgid="938685362320735167">"يتعذّر الشحن باستخدام USB."</string>
<string name="invalid_charger_text" msgid="2339310107232691577">"استخدم الشاحن المرفق بجهازك."</string>
<string name="battery_saver_confirmation_title" msgid="1234998463717398453">"هل تريد تفعيل ميزة توفير شحن البطارية؟"</string>
<string name="battery_saver_confirmation_title_generic" msgid="2299231884234959849">"لمحة عن ميزة \"توفير شحن البطارية\""</string>
<string name="battery_saver_confirmation_ok" msgid="5042136476802816494">"تفعيل"</string>
- <string name="battery_saver_start_action" msgid="4553256017945469937">"هل تريد تفعيل ميزة توفير شحن البطارية؟"</string>
+ <string name="battery_saver_start_action" msgid="8353766979886287140">"تفعيل"</string>
+ <string name="battery_saver_dismiss_action" msgid="7199342621040014738">"لا، شكرًا"</string>
<string name="status_bar_settings_auto_rotation" msgid="8329080442278431708">"التدوير التلقائي للشاشة"</string>
<string name="usb_device_permission_prompt" msgid="4414719028369181772">"هل تريد السماح لتطبيق <xliff:g id="APPLICATION">%1$s</xliff:g> بالدخول إلى <xliff:g id="USB_DEVICE">%2$s</xliff:g>؟"</string>
<string name="usb_device_permission_prompt_warn" msgid="2309129784984063656">"هل تريد السماح لتطبيق <xliff:g id="APPLICATION">%1$s</xliff:g> بالدخول إلى <xliff:g id="USB_DEVICE">%2$s</xliff:g>؟\nلم يتم منح هذا التطبيق إذن تسجيل، ولكن يمكنه تسجيل الصوت من خلال جهاز USB هذا."</string>
@@ -133,8 +131,7 @@
<string name="biometric_dialog_face_icon_description_authenticated" msgid="2242167416140740920">"تمّت مصادقة الوجه."</string>
<string name="biometric_dialog_face_icon_description_confirmed" msgid="7918067993953940778">"تمّ التأكيد."</string>
<string name="biometric_dialog_tap_confirm" msgid="9166350738859143358">"يمكنك النقر على \"تأكيد\" لإكمال المهمة."</string>
- <!-- no translation found for biometric_dialog_tap_confirm_with_face (1597899891472340950) -->
- <skip />
+ <string name="biometric_dialog_tap_confirm_with_face" msgid="1597899891472340950">"تم فتح قفل الجهاز بالتعرف على وجهك. اضغط للمتابعة."</string>
<string name="biometric_dialog_authenticated" msgid="7337147327545272484">"مصادقة"</string>
<string name="biometric_dialog_use_pin" msgid="8385294115283000709">"استخدام رقم تعريف شخصي"</string>
<string name="biometric_dialog_use_pattern" msgid="2315593393167211194">"استخدام نقش"</string>
@@ -474,8 +471,8 @@
<string name="wallet_secondary_label_device_locked" msgid="5175862019125370506">"فتح القفل للاستخدام"</string>
<string name="wallet_error_generic" msgid="257704570182963611">"حدثت مشكلة أثناء الحصول على البطاقات، يُرجى إعادة المحاولة لاحقًا."</string>
<string name="wallet_lockscreen_settings_label" msgid="3539105300870383570">"إعدادات شاشة القفل"</string>
- <string name="qr_code_scanner_title" msgid="5660820608548306581">"رمز الاستجابة السريعة"</string>
- <string name="qr_code_scanner_description" msgid="7937603775306661863">"انقر للمسح ضوئيًا"</string>
+ <!-- no translation found for qr_code_scanner_title (5290201053875420785) -->
+ <skip />
<string name="status_bar_work" msgid="5238641949837091056">"الملف الشخصي للعمل"</string>
<string name="status_bar_airplane" msgid="4848702508684541009">"وضع الطيران"</string>
<string name="zen_alarm_warning" msgid="7844303238486849503">"لن تسمع المنبّه القادم في <xliff:g id="WHEN">%1$s</xliff:g>"</string>
@@ -851,6 +848,7 @@
<string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"إقران جهاز جديد"</string>
<string name="media_output_dialog_launch_app_text" msgid="1527413319632586259">"لبث هذه الجلسة، يُرجى فتح التطبيق"</string>
<string name="media_output_dialog_unknown_launch_app_name" msgid="1084899329829371336">"تطبيق غير معروف"</string>
+ <string name="media_output_dialog_button_stop_casting" msgid="6581379537930199189">"إيقاف البث"</string>
<string name="build_number_clip_data_label" msgid="3623176728412560914">"رقم الإصدار"</string>
<string name="build_number_copy_toast" msgid="877720921605503046">"تم نسخ رقم الإصدار إلى الحافظة."</string>
<string name="basic_status" msgid="2315371112182658176">"محادثة مفتوحة"</string>
@@ -944,8 +942,6 @@
<string name="dream_overlay_status_bar_wifi_off" msgid="4497069245055003582">"شبكة Wi‑Fi غير متاحة"</string>
<string name="dream_overlay_status_bar_priority_mode" msgid="5428462123314728739">"وضع الأولوية"</string>
<string name="dream_overlay_status_bar_alarm_set" msgid="566707328356590886">"تم ضبط المنبه."</string>
- <string name="dream_overlay_status_bar_assistant_guest_mode_enabled" msgid="3715897096012469615">"تم تفعيل وضع الضيف لاستخدام \"مساعد Google\"."</string>
<string name="dream_overlay_status_bar_camera_mic_off" msgid="3199425257833773569">"الكاميرا والميكروفون غير مفعّلين."</string>
- <!-- no translation found for dream_overlay_status_bar_notification_indicator (8091389255691081711) -->
- <skip />
+ <string name="dream_overlay_status_bar_notification_indicator" msgid="8091389255691081711">"{count,plural, =1{إشعار واحد}zero{# إشعار}two{إشعاران}few{# إشعارات}many{# إشعارًا}other{# إشعار}}"</string>
</resources>
diff --git a/packages/SystemUI/res/values-as/strings.xml b/packages/SystemUI/res/values-as/strings.xml
index 00f7790..7bb97a7 100644
--- a/packages/SystemUI/res/values-as/strings.xml
+++ b/packages/SystemUI/res/values-as/strings.xml
@@ -20,19 +20,17 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_label" msgid="4811759950673118541">"ছিষ্টেম ইউআই"</string>
- <!-- no translation found for battery_low_title (5319680173344341779) -->
- <skip />
- <!-- no translation found for battery_low_description (3282977755476423966) -->
- <skip />
- <!-- no translation found for battery_low_intro (5148725009653088790) -->
- <skip />
+ <string name="battery_low_title" msgid="5319680173344341779">"বেটাৰী সঞ্চয়কাৰী অন কৰিবনে?"</string>
+ <string name="battery_low_description" msgid="3282977755476423966">"আপোনাৰ <xliff:g id="PERCENTAGE">%s</xliff:g> বেটাৰী বাকী আছে। বেটাৰী সঞ্চয়কাৰীয়ে গাঢ় ৰঙৰ থীম অন কৰে, নেপথ্যৰ কাৰ্যকলাপ সীমাবদ্ধ কৰে আৰু জাননী পলম কৰে।"</string>
+ <string name="battery_low_intro" msgid="5148725009653088790">"বেটাৰী সঞ্চয়কাৰীয়ে গাঢ় ৰঙৰ থীম অন কৰে, নেপথ্যৰ কাৰ্যকলাপ সীমাবদ্ধ কৰে আৰু জাননী পলম কৰে।"</string>
<string name="battery_low_percent_format" msgid="4276661262843170964">"<xliff:g id="PERCENTAGE">%s</xliff:g> বাকী আছে"</string>
<string name="invalid_charger_title" msgid="938685362320735167">"ইউএছবি জৰিয়তে চ্চাৰ্জ কৰিব নোৱাৰি"</string>
<string name="invalid_charger_text" msgid="2339310107232691577">"আপোনাৰ ডিভাইচৰ লগত পোৱা চ্চাৰ্জাৰটো ব্যৱহাৰ কৰক।"</string>
<string name="battery_saver_confirmation_title" msgid="1234998463717398453">"বেটাৰী সঞ্চয়কাৰী অন কৰেনে?"</string>
<string name="battery_saver_confirmation_title_generic" msgid="2299231884234959849">"বেটাৰী সঞ্চয়কাৰীৰ বিষয়ে"</string>
<string name="battery_saver_confirmation_ok" msgid="5042136476802816494">"অন কৰক"</string>
- <string name="battery_saver_start_action" msgid="4553256017945469937">"বেটাৰী সঞ্চয়কাৰী অন কৰক"</string>
+ <string name="battery_saver_start_action" msgid="8353766979886287140">"অন কৰক"</string>
+ <string name="battery_saver_dismiss_action" msgid="7199342621040014738">"নালাগে, ধন্যবাদ"</string>
<string name="status_bar_settings_auto_rotation" msgid="8329080442278431708">"স্বয়ং-ঘূৰ্ণন স্ক্ৰীন"</string>
<string name="usb_device_permission_prompt" msgid="4414719028369181772">"<xliff:g id="USB_DEVICE">%2$s</xliff:g>ত প্ৰৱেশ কৰিবলৈ <xliff:g id="APPLICATION">%1$s</xliff:g>ক অনুমতি দিবনে?"</string>
<string name="usb_device_permission_prompt_warn" msgid="2309129784984063656">"<xliff:g id="APPLICATION">%1$s</xliff:g>ক <xliff:g id="USB_DEVICE">%2$s</xliff:g> এক্সেছ কৰিবলৈ অনুমতি দিবনে?\nএই এপ্টোক ৰেকর্ড কৰাৰ অনুমতি দিয়া হোৱা নাই কিন্তু ই এই ইউএছবি ডিভাইচটোৰ জৰিয়তে অডিঅ\' ৰেকর্ড কৰিব পাৰে।"</string>
@@ -133,8 +131,7 @@
<string name="biometric_dialog_face_icon_description_authenticated" msgid="2242167416140740920">"মুখমণ্ডলৰ বিশ্বাসযোগ্যতা প্ৰমাণীকৰণ কৰা হ’ল"</string>
<string name="biometric_dialog_face_icon_description_confirmed" msgid="7918067993953940778">"নিশ্চিত কৰিলে"</string>
<string name="biometric_dialog_tap_confirm" msgid="9166350738859143358">"সম্পূৰ্ণ কৰিবলৈ নিশ্চিত কৰক-ত টিপক"</string>
- <!-- no translation found for biometric_dialog_tap_confirm_with_face (1597899891472340950) -->
- <skip />
+ <string name="biometric_dialog_tap_confirm_with_face" msgid="1597899891472340950">"আপোনাৰ মুখাৱয়বৰ দ্বাৰা আনলক কৰা হৈছে। অব্যাহত ৰাখিবলৈ দবাওক।"</string>
<string name="biometric_dialog_authenticated" msgid="7337147327545272484">"বিশ্বাসযোগ্যতা প্ৰমাণীকৰণ কৰা হ’ল"</string>
<string name="biometric_dialog_use_pin" msgid="8385294115283000709">"পিন ব্যৱহাৰ কৰক"</string>
<string name="biometric_dialog_use_pattern" msgid="2315593393167211194">"আৰ্হি ব্যৱহাৰ কৰক"</string>
@@ -462,8 +459,8 @@
<string name="wallet_secondary_label_device_locked" msgid="5175862019125370506">"ব্যৱহাৰ কৰিবলৈ আনলক কৰক"</string>
<string name="wallet_error_generic" msgid="257704570182963611">"আপোনাৰ কাৰ্ড লাভ কৰোঁতে এটা সমস্যা হৈছে, অনুগ্ৰহ কৰি পাছত পুনৰ চেষ্টা কৰক"</string>
<string name="wallet_lockscreen_settings_label" msgid="3539105300870383570">"লক স্ক্ৰীনৰ ছেটিং"</string>
- <string name="qr_code_scanner_title" msgid="5660820608548306581">"কিউআৰ ক\'ড"</string>
- <string name="qr_code_scanner_description" msgid="7937603775306661863">"স্কেন কৰিবলৈ টিপক"</string>
+ <!-- no translation found for qr_code_scanner_title (5290201053875420785) -->
+ <skip />
<string name="status_bar_work" msgid="5238641949837091056">"কৰ্মস্থানৰ প্ৰ\'ফাইল"</string>
<string name="status_bar_airplane" msgid="4848702508684541009">"এয়াৰপ্লেইন ম\'ড"</string>
<string name="zen_alarm_warning" msgid="7844303238486849503">"আপুনি আপোনাৰ পিছৰটো এলাৰ্ম <xliff:g id="WHEN">%1$s</xliff:g> বজাত শুনা নাপাব"</string>
@@ -827,6 +824,7 @@
<string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"নতুন ডিভাইচ পেয়াৰ কৰক"</string>
<string name="media_output_dialog_launch_app_text" msgid="1527413319632586259">"এই ছেশ্বনটো কাষ্ট কৰিবলৈ, অনুগ্ৰহ কৰি এপ্টো খোলক"</string>
<string name="media_output_dialog_unknown_launch_app_name" msgid="1084899329829371336">"অজ্ঞাত এপ্"</string>
+ <string name="media_output_dialog_button_stop_casting" msgid="6581379537930199189">"কাষ্ট বন্ধ কৰক"</string>
<string name="build_number_clip_data_label" msgid="3623176728412560914">"বিল্ডৰ নম্বৰ"</string>
<string name="build_number_copy_toast" msgid="877720921605503046">"ক্লিপব’ৰ্ডলৈ বিল্ডৰ নম্বৰ প্ৰতিলিপি কৰা হ’ল।"</string>
<string name="basic_status" msgid="2315371112182658176">"বাৰ্তালাপ খোলক"</string>
@@ -916,8 +914,6 @@
<string name="dream_overlay_status_bar_wifi_off" msgid="4497069245055003582">"ৱাই-ফাই উপলব্ধ নহয়"</string>
<string name="dream_overlay_status_bar_priority_mode" msgid="5428462123314728739">"অগ্ৰাধিকাৰ ম’ড"</string>
<string name="dream_overlay_status_bar_alarm_set" msgid="566707328356590886">"এলাৰ্ম ছেট কৰা হ’ল"</string>
- <string name="dream_overlay_status_bar_assistant_guest_mode_enabled" msgid="3715897096012469615">"Assistantৰ অতিথি ম’ড সক্ষম কৰা হৈছে"</string>
<string name="dream_overlay_status_bar_camera_mic_off" msgid="3199425257833773569">"কেমেৰা আৰু মাইক অফ হৈ আছে"</string>
- <!-- no translation found for dream_overlay_status_bar_notification_indicator (8091389255691081711) -->
- <skip />
+ <string name="dream_overlay_status_bar_notification_indicator" msgid="8091389255691081711">"{count,plural, =1{# টা জাননী}one{# টা জাননী}other{# টা জাননী}}"</string>
</resources>
diff --git a/packages/SystemUI/res/values-az/strings.xml b/packages/SystemUI/res/values-az/strings.xml
index a1956b3..a796a20 100644
--- a/packages/SystemUI/res/values-az/strings.xml
+++ b/packages/SystemUI/res/values-az/strings.xml
@@ -20,19 +20,17 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_label" msgid="4811759950673118541">"Sistemin İstifadə İnterfeysi"</string>
- <!-- no translation found for battery_low_title (5319680173344341779) -->
- <skip />
- <!-- no translation found for battery_low_description (3282977755476423966) -->
- <skip />
- <!-- no translation found for battery_low_intro (5148725009653088790) -->
- <skip />
+ <string name="battery_low_title" msgid="5319680173344341779">"Enerjiyə Qənaət aktiv edilsin?"</string>
+ <string name="battery_low_description" msgid="3282977755476423966">"<xliff:g id="PERCENTAGE">%s</xliff:g> enerji qalıb. Enerjiyə Qənaət rejimi Tünd temanı aktivləşdirir, arxa fon fəaliyyətini məhdudlaşdırır və bildirişləri gecikdirir."</string>
+ <string name="battery_low_intro" msgid="5148725009653088790">"Enerjiyə Qənaət rejimi Tünd temanı aktivləşdirir, arxa fon fəaliyyətini məhdudlaşdırır və bildirişləri gecikdirir."</string>
<string name="battery_low_percent_format" msgid="4276661262843170964">"<xliff:g id="PERCENTAGE">%s</xliff:g> qalır"</string>
<string name="invalid_charger_title" msgid="938685362320735167">"USB vasitəsilə enerji yığa bilməz"</string>
<string name="invalid_charger_text" msgid="2339310107232691577">"Cihazla verilən adapterdən istifadə edin"</string>
<string name="battery_saver_confirmation_title" msgid="1234998463717398453">"Batareya Qənaəti aktiv edilsin?"</string>
<string name="battery_saver_confirmation_title_generic" msgid="2299231884234959849">"Enerjiyə Qənaət Haqqında"</string>
<string name="battery_saver_confirmation_ok" msgid="5042136476802816494">"Aktivləşdirin"</string>
- <string name="battery_saver_start_action" msgid="4553256017945469937">"Batareya Qənaətini aktiv edin"</string>
+ <string name="battery_saver_start_action" msgid="8353766979886287140">"Aktiv edin"</string>
+ <string name="battery_saver_dismiss_action" msgid="7199342621040014738">"Xeyr, təşəkkür"</string>
<string name="status_bar_settings_auto_rotation" msgid="8329080442278431708">"Ekranın avtomatik dönməsi"</string>
<string name="usb_device_permission_prompt" msgid="4414719028369181772">"<xliff:g id="APPLICATION">%1$s</xliff:g> tətbiqinə <xliff:g id="USB_DEVICE">%2$s</xliff:g> cihazına giriş icazəsi verilsin?"</string>
<string name="usb_device_permission_prompt_warn" msgid="2309129784984063656">"<xliff:g id="APPLICATION">%1$s</xliff:g> tətbiqinə <xliff:g id="USB_DEVICE">%2$s</xliff:g> cihazına giriş icazəsi verilsin?\nBu tətbiqə qeydə almaq icazəsi verilməyib lakin, bu USB vasitəsilə səs yaza bilər."</string>
@@ -133,8 +131,7 @@
<string name="biometric_dialog_face_icon_description_authenticated" msgid="2242167416140740920">"Üz doğrulandı"</string>
<string name="biometric_dialog_face_icon_description_confirmed" msgid="7918067993953940778">"Təsdiqləndi"</string>
<string name="biometric_dialog_tap_confirm" msgid="9166350738859143358">"Tamamlamaq üçün \"Təsdiq edin\" seçiminə toxunun"</string>
- <!-- no translation found for biometric_dialog_tap_confirm_with_face (1597899891472340950) -->
- <skip />
+ <string name="biometric_dialog_tap_confirm_with_face" msgid="1597899891472340950">"Üzünüzlə kiliddən çıxarılıb. Davam etmək üçün basın."</string>
<string name="biometric_dialog_authenticated" msgid="7337147327545272484">"Doğrulandı"</string>
<string name="biometric_dialog_use_pin" msgid="8385294115283000709">"PIN istifadə edin"</string>
<string name="biometric_dialog_use_pattern" msgid="2315593393167211194">"Model istifadə edin"</string>
@@ -462,8 +459,7 @@
<string name="wallet_secondary_label_device_locked" msgid="5175862019125370506">"İstifadə etmək üçün kiliddən çıxarın"</string>
<string name="wallet_error_generic" msgid="257704570182963611">"Kartların əldə edilməsində problem oldu, sonra yenidən cəhd edin"</string>
<string name="wallet_lockscreen_settings_label" msgid="3539105300870383570">"Kilid ekranı ayarları"</string>
- <string name="qr_code_scanner_title" msgid="5660820608548306581">"QR kodu"</string>
- <string name="qr_code_scanner_description" msgid="7937603775306661863">"Skanlamaq üçün toxunun"</string>
+ <string name="qr_code_scanner_title" msgid="5290201053875420785">"QR kodu skanlayın"</string>
<string name="status_bar_work" msgid="5238641949837091056">"İş profili"</string>
<string name="status_bar_airplane" msgid="4848702508684541009">"Təyyarə rejimi"</string>
<string name="zen_alarm_warning" msgid="7844303238486849503">"<xliff:g id="WHEN">%1$s</xliff:g> zaman növbəti xəbərdarlığınızı eşitməyəcəksiniz"</string>
@@ -827,6 +823,7 @@
<string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"Cihaz əlavə edin"</string>
<string name="media_output_dialog_launch_app_text" msgid="1527413319632586259">"Bu sessiyanı yayımlamaq üçün tətbiqi açın."</string>
<string name="media_output_dialog_unknown_launch_app_name" msgid="1084899329829371336">"Naməlum tətbiq"</string>
+ <string name="media_output_dialog_button_stop_casting" msgid="6581379537930199189">"Yayımı dayandırın"</string>
<string name="build_number_clip_data_label" msgid="3623176728412560914">"Montaj nömrəsi"</string>
<string name="build_number_copy_toast" msgid="877720921605503046">"Versiya nömrəsi mübadilə buferinə kopyalandı."</string>
<string name="basic_status" msgid="2315371112182658176">"Açıq söhbət"</string>
@@ -916,8 +913,6 @@
<string name="dream_overlay_status_bar_wifi_off" msgid="4497069245055003582">"Wi‑Fi əlçatan deyil"</string>
<string name="dream_overlay_status_bar_priority_mode" msgid="5428462123314728739">"Prioritet rejimi"</string>
<string name="dream_overlay_status_bar_alarm_set" msgid="566707328356590886">"Siqnal ayarlanıb"</string>
- <string name="dream_overlay_status_bar_assistant_guest_mode_enabled" msgid="3715897096012469615">"Assistent qonaq rejimi aktivdir"</string>
<string name="dream_overlay_status_bar_camera_mic_off" msgid="3199425257833773569">"Kamera və mikrofon deaktivdir"</string>
- <!-- no translation found for dream_overlay_status_bar_notification_indicator (8091389255691081711) -->
- <skip />
+ <string name="dream_overlay_status_bar_notification_indicator" msgid="8091389255691081711">"{count,plural, =1{# bildiriş}other{# bildiriş}}"</string>
</resources>
diff --git a/packages/SystemUI/res/values-b+sr+Latn/strings.xml b/packages/SystemUI/res/values-b+sr+Latn/strings.xml
index 2019e9d..cd6b9cc 100644
--- a/packages/SystemUI/res/values-b+sr+Latn/strings.xml
+++ b/packages/SystemUI/res/values-b+sr+Latn/strings.xml
@@ -20,19 +20,17 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_label" msgid="4811759950673118541">"UI sistema"</string>
- <!-- no translation found for battery_low_title (5319680173344341779) -->
- <skip />
- <!-- no translation found for battery_low_description (3282977755476423966) -->
- <skip />
- <!-- no translation found for battery_low_intro (5148725009653088790) -->
- <skip />
+ <string name="battery_low_title" msgid="5319680173344341779">"Želite li da uključite Uštedu baterije?"</string>
+ <string name="battery_low_description" msgid="3282977755476423966">"Preostali nivo napunjenosti baterije je <xliff:g id="PERCENTAGE">%s</xliff:g>. Ušteda baterije uključuje Tamnu temu, ograničava aktivnosti u pozadini i odlaže obaveštenja."</string>
+ <string name="battery_low_intro" msgid="5148725009653088790">"Ušteda baterije uključuje Tamnu temu, ograničava aktivnosti u pozadini i odlaže obaveštenja."</string>
<string name="battery_low_percent_format" msgid="4276661262843170964">"Još <xliff:g id="PERCENTAGE">%s</xliff:g>"</string>
<string name="invalid_charger_title" msgid="938685362320735167">"Punjenje preko USB-a nije uspelo"</string>
<string name="invalid_charger_text" msgid="2339310107232691577">"Koristite punjač koji ste dobili uz uređaj"</string>
<string name="battery_saver_confirmation_title" msgid="1234998463717398453">"Želite da uključite Uštedu baterije?"</string>
<string name="battery_saver_confirmation_title_generic" msgid="2299231884234959849">"O Uštedi baterije"</string>
<string name="battery_saver_confirmation_ok" msgid="5042136476802816494">"Uključi"</string>
- <string name="battery_saver_start_action" msgid="4553256017945469937">"Uključi Uštedu baterije"</string>
+ <string name="battery_saver_start_action" msgid="8353766979886287140">"Uključi"</string>
+ <string name="battery_saver_dismiss_action" msgid="7199342621040014738">"Ne, hvala"</string>
<string name="status_bar_settings_auto_rotation" msgid="8329080442278431708">"Automatsko rotiranje ekrana"</string>
<string name="usb_device_permission_prompt" msgid="4414719028369181772">"Želite li da dozvolite da <xliff:g id="APPLICATION">%1$s</xliff:g> pristupa uređaju <xliff:g id="USB_DEVICE">%2$s</xliff:g>?"</string>
<string name="usb_device_permission_prompt_warn" msgid="2309129784984063656">"Želite li da dozvolite da <xliff:g id="APPLICATION">%1$s</xliff:g> pristupa uređaju <xliff:g id="USB_DEVICE">%2$s</xliff:g>?\nOva aplikacija nema dozvolu za snimanje, ali bi mogla da snima zvuk pomoću ovog USB uređaja."</string>
@@ -133,8 +131,7 @@
<string name="biometric_dialog_face_icon_description_authenticated" msgid="2242167416140740920">"Lice je potvrđeno"</string>
<string name="biometric_dialog_face_icon_description_confirmed" msgid="7918067993953940778">"Potvrđeno"</string>
<string name="biometric_dialog_tap_confirm" msgid="9166350738859143358">"Dodirnite Potvrdi da biste završili"</string>
- <!-- no translation found for biometric_dialog_tap_confirm_with_face (1597899891472340950) -->
- <skip />
+ <string name="biometric_dialog_tap_confirm_with_face" msgid="1597899891472340950">"Otključali ste licem. Pritisnite da biste nastavili."</string>
<string name="biometric_dialog_authenticated" msgid="7337147327545272484">"Identitet je potvrđen"</string>
<string name="biometric_dialog_use_pin" msgid="8385294115283000709">"Koristite PIN"</string>
<string name="biometric_dialog_use_pattern" msgid="2315593393167211194">"Koristite šablon"</string>
@@ -465,8 +462,7 @@
<string name="wallet_secondary_label_device_locked" msgid="5175862019125370506">"Otključaj radi korišćenja"</string>
<string name="wallet_error_generic" msgid="257704570182963611">"Došlo je do problema pri preuzimanju kartica. Probajte ponovo kasnije"</string>
<string name="wallet_lockscreen_settings_label" msgid="3539105300870383570">"Podešavanja zaključanog ekrana"</string>
- <string name="qr_code_scanner_title" msgid="5660820608548306581">"QR kôd"</string>
- <string name="qr_code_scanner_description" msgid="7937603775306661863">"Dodirnite da biste skenirali"</string>
+ <string name="qr_code_scanner_title" msgid="5290201053875420785">"Skenirajte QR kôd"</string>
<string name="status_bar_work" msgid="5238641949837091056">"Poslovni profil"</string>
<string name="status_bar_airplane" msgid="4848702508684541009">"Režim rada u avionu"</string>
<string name="zen_alarm_warning" msgid="7844303238486849503">"Nećete čuti sledeći alarm u <xliff:g id="WHEN">%1$s</xliff:g>"</string>
@@ -833,6 +829,7 @@
<string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"Upari novi uređaj"</string>
<string name="media_output_dialog_launch_app_text" msgid="1527413319632586259">"Da biste prebacivali ovu sesiju, otvorite aplikaciju."</string>
<string name="media_output_dialog_unknown_launch_app_name" msgid="1084899329829371336">"Nepoznata aplikacija"</string>
+ <string name="media_output_dialog_button_stop_casting" msgid="6581379537930199189">"Zaustavi prebacivanje"</string>
<string name="build_number_clip_data_label" msgid="3623176728412560914">"Broj verzije"</string>
<string name="build_number_copy_toast" msgid="877720921605503046">"Broj verzije je kopiran u privremenu memoriju."</string>
<string name="basic_status" msgid="2315371112182658176">"Otvorite konverzaciju"</string>
@@ -923,8 +920,6 @@
<string name="dream_overlay_status_bar_wifi_off" msgid="4497069245055003582">"WiFi nije dostupan"</string>
<string name="dream_overlay_status_bar_priority_mode" msgid="5428462123314728739">"Prioritetni režim"</string>
<string name="dream_overlay_status_bar_alarm_set" msgid="566707328356590886">"Alarm je podešen"</string>
- <string name="dream_overlay_status_bar_assistant_guest_mode_enabled" msgid="3715897096012469615">"Omogućen je režim gosta u Pomoćniku"</string>
<string name="dream_overlay_status_bar_camera_mic_off" msgid="3199425257833773569">"Kamera i mikrofon su isključeni"</string>
- <!-- no translation found for dream_overlay_status_bar_notification_indicator (8091389255691081711) -->
- <skip />
+ <string name="dream_overlay_status_bar_notification_indicator" msgid="8091389255691081711">"{count,plural, =1{# obaveštenje}one{# obaveštenje}few{# obaveštenja}other{# obaveštenja}}"</string>
</resources>
diff --git a/packages/SystemUI/res/values-be/strings.xml b/packages/SystemUI/res/values-be/strings.xml
index c10a36d..0380a76 100644
--- a/packages/SystemUI/res/values-be/strings.xml
+++ b/packages/SystemUI/res/values-be/strings.xml
@@ -20,19 +20,17 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_label" msgid="4811759950673118541">"Інтэрфейс сістэмы"</string>
- <!-- no translation found for battery_low_title (5319680173344341779) -->
- <skip />
- <!-- no translation found for battery_low_description (3282977755476423966) -->
- <skip />
- <!-- no translation found for battery_low_intro (5148725009653088790) -->
- <skip />
+ <string name="battery_low_title" msgid="5319680173344341779">"Уключыць рэжым энергазберажэння?"</string>
+ <string name="battery_low_description" msgid="3282977755476423966">"Засталося <xliff:g id="PERCENTAGE">%s</xliff:g> зараду акумулятара. Рэжым энергазберажэння ўключае цёмную тэму, абмяжоўвае дзеянні ў фонавым рэжыме і затрымлівае апавяшчэнні."</string>
+ <string name="battery_low_intro" msgid="5148725009653088790">"Рэжым энергазберажэння ўключае цёмную тэму, абмяжоўвае дзеянні ў фонавым рэжыме і затрымлівае апавяшчэнні."</string>
<string name="battery_low_percent_format" msgid="4276661262843170964">"Засталося <xliff:g id="PERCENTAGE">%s</xliff:g>"</string>
<string name="invalid_charger_title" msgid="938685362320735167">"Не ўдалося выканаць зарадку праз USB"</string>
<string name="invalid_charger_text" msgid="2339310107232691577">"Выкарыстоўвайце зараднае прыстасаванне з камплекта прылады"</string>
<string name="battery_saver_confirmation_title" msgid="1234998463717398453">"Уключыць рэжым эканоміі зараду?"</string>
<string name="battery_saver_confirmation_title_generic" msgid="2299231884234959849">"Інфармацыя пра рэжым эканоміі зараду"</string>
<string name="battery_saver_confirmation_ok" msgid="5042136476802816494">"Уключыць"</string>
- <string name="battery_saver_start_action" msgid="4553256017945469937">"Уключыць рэжым эканоміі зараду"</string>
+ <string name="battery_saver_start_action" msgid="8353766979886287140">"Уключыць"</string>
+ <string name="battery_saver_dismiss_action" msgid="7199342621040014738">"Не, дзякуй"</string>
<string name="status_bar_settings_auto_rotation" msgid="8329080442278431708">"Аўтаматычны паварот экрана"</string>
<string name="usb_device_permission_prompt" msgid="4414719028369181772">"Дазволіць праграме <xliff:g id="APPLICATION">%1$s</xliff:g> доступ да прылады <xliff:g id="USB_DEVICE">%2$s</xliff:g>?"</string>
<string name="usb_device_permission_prompt_warn" msgid="2309129784984063656">"Даць праграме \"<xliff:g id="APPLICATION">%1$s</xliff:g>\" доступ да прылады \"<xliff:g id="USB_DEVICE">%2$s</xliff:g>\"?\nУ гэтай праграмы няма дазволу на запіс, аднак яна зможа запісваць аўдыя праз гэту прыладу USB."</string>
@@ -133,8 +131,7 @@
<string name="biometric_dialog_face_icon_description_authenticated" msgid="2242167416140740920">"Твар распазнаны"</string>
<string name="biometric_dialog_face_icon_description_confirmed" msgid="7918067993953940778">"Пацверджана"</string>
<string name="biometric_dialog_tap_confirm" msgid="9166350738859143358">"Націсніце \"Пацвердзіць\", каб завяршыць"</string>
- <!-- no translation found for biometric_dialog_tap_confirm_with_face (1597899891472340950) -->
- <skip />
+ <string name="biometric_dialog_tap_confirm_with_face" msgid="1597899891472340950">"Разблакіравана распазнаваннем твару. Націсніце для працягу."</string>
<string name="biometric_dialog_authenticated" msgid="7337147327545272484">"Распазнана"</string>
<string name="biometric_dialog_use_pin" msgid="8385294115283000709">"Увесці PIN-код"</string>
<string name="biometric_dialog_use_pattern" msgid="2315593393167211194">"Выкарыстаць узор разблакіроўкі"</string>
@@ -468,8 +465,8 @@
<string name="wallet_secondary_label_device_locked" msgid="5175862019125370506">"Разблакіраваць для выкарыстання"</string>
<string name="wallet_error_generic" msgid="257704570182963611">"Узнікла праблема з загрузкай вашых карт. Паўтарыце спробу пазней"</string>
<string name="wallet_lockscreen_settings_label" msgid="3539105300870383570">"Налады экрана блакіроўкі"</string>
- <string name="qr_code_scanner_title" msgid="5660820608548306581">"QR-код"</string>
- <string name="qr_code_scanner_description" msgid="7937603775306661863">"Націсніце, каб адсканіраваць"</string>
+ <!-- no translation found for qr_code_scanner_title (5290201053875420785) -->
+ <skip />
<string name="status_bar_work" msgid="5238641949837091056">"Працоўны профіль"</string>
<string name="status_bar_airplane" msgid="4848702508684541009">"Рэжым палёту"</string>
<string name="zen_alarm_warning" msgid="7844303238486849503">"Вы не пачуеце наступны будзільнік <xliff:g id="WHEN">%1$s</xliff:g>"</string>
@@ -839,6 +836,7 @@
<string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"Спалучыць з новай прыладай"</string>
<string name="media_output_dialog_launch_app_text" msgid="1527413319632586259">"Для трансляцыі гэтага сеанса адкрыйце праграму."</string>
<string name="media_output_dialog_unknown_launch_app_name" msgid="1084899329829371336">"Невядомая праграма"</string>
+ <string name="media_output_dialog_button_stop_casting" msgid="6581379537930199189">"Спыніць трансляцыю"</string>
<string name="build_number_clip_data_label" msgid="3623176728412560914">"Нумар зборкі"</string>
<string name="build_number_copy_toast" msgid="877720921605503046">"Нумар зборкі скапіраваны ў буфер абмену."</string>
<string name="basic_status" msgid="2315371112182658176">"Адкрытая размова"</string>
@@ -930,8 +928,6 @@
<string name="dream_overlay_status_bar_wifi_off" msgid="4497069245055003582">"Сетка Wi‑Fi недаступная"</string>
<string name="dream_overlay_status_bar_priority_mode" msgid="5428462123314728739">"Прыярытэтны рэжым"</string>
<string name="dream_overlay_status_bar_alarm_set" msgid="566707328356590886">"Будзільнік зададзены"</string>
- <string name="dream_overlay_status_bar_assistant_guest_mode_enabled" msgid="3715897096012469615">"Гасцявы рэжым для Памочніка ўключаны"</string>
<string name="dream_overlay_status_bar_camera_mic_off" msgid="3199425257833773569">"Камера і мікрафон выключаны"</string>
- <!-- no translation found for dream_overlay_status_bar_notification_indicator (8091389255691081711) -->
- <skip />
+ <string name="dream_overlay_status_bar_notification_indicator" msgid="8091389255691081711">"{count,plural, =1{# апавяшчэнне}one{# апавяшчэнне}few{# апавяшчэнні}many{# апавяшчэнняў}other{# апавяшчэння}}"</string>
</resources>
diff --git a/packages/SystemUI/res/values-bg/strings.xml b/packages/SystemUI/res/values-bg/strings.xml
index a107504..f56e57d 100644
--- a/packages/SystemUI/res/values-bg/strings.xml
+++ b/packages/SystemUI/res/values-bg/strings.xml
@@ -20,19 +20,17 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_label" msgid="4811759950673118541">"Системен ПИ"</string>
- <!-- no translation found for battery_low_title (5319680173344341779) -->
- <skip />
- <!-- no translation found for battery_low_description (3282977755476423966) -->
- <skip />
- <!-- no translation found for battery_low_intro (5148725009653088790) -->
- <skip />
+ <string name="battery_low_title" msgid="5319680173344341779">"Да се включи ли режимът за запазване на батерията?"</string>
+ <string name="battery_low_description" msgid="3282977755476423966">"Оставащ заряд на батерията: <xliff:g id="PERCENTAGE">%s</xliff:g>. Режимът за запазване на батерията включва тъмната тема, ограничава активността на заден план и отлага известията."</string>
+ <string name="battery_low_intro" msgid="5148725009653088790">"Режимът за запазване на батерията включва тъмната тема, ограничава активността на заден план и отлага известията."</string>
<string name="battery_low_percent_format" msgid="4276661262843170964">"Остава/т <xliff:g id="PERCENTAGE">%s</xliff:g>"</string>
<string name="invalid_charger_title" msgid="938685362320735167">"Зареждането през USB не е възможно"</string>
<string name="invalid_charger_text" msgid="2339310107232691577">"Използвайте оригиналното зарядно устройство"</string>
<string name="battery_saver_confirmation_title" msgid="1234998463717398453">"Да се включи ли режимът за запазване на батерията?"</string>
<string name="battery_saver_confirmation_title_generic" msgid="2299231884234959849">"Всичко за режима за запазване на батерията"</string>
<string name="battery_saver_confirmation_ok" msgid="5042136476802816494">"Включване"</string>
- <string name="battery_saver_start_action" msgid="4553256017945469937">"Включване на режима за запазване на батерията"</string>
+ <string name="battery_saver_start_action" msgid="8353766979886287140">"Включване"</string>
+ <string name="battery_saver_dismiss_action" msgid="7199342621040014738">"Не, благодаря"</string>
<string name="status_bar_settings_auto_rotation" msgid="8329080442278431708">"Авт. завъртане на екрана"</string>
<string name="usb_device_permission_prompt" msgid="4414719028369181772">"Да се разреши ли на <xliff:g id="APPLICATION">%1$s</xliff:g> достъп до <xliff:g id="USB_DEVICE">%2$s</xliff:g>?"</string>
<string name="usb_device_permission_prompt_warn" msgid="2309129784984063656">"Наистина ли искате да разрешите на <xliff:g id="APPLICATION">%1$s</xliff:g> достъп до <xliff:g id="USB_DEVICE">%2$s</xliff:g>?\nНа приложението не е предоставено разрешение за записване, но е възможно да запише звук чрез това USB устройство."</string>
@@ -133,8 +131,7 @@
<string name="biometric_dialog_face_icon_description_authenticated" msgid="2242167416140740920">"Лицето е удостоверено"</string>
<string name="biometric_dialog_face_icon_description_confirmed" msgid="7918067993953940778">"Потвърдено"</string>
<string name="biometric_dialog_tap_confirm" msgid="9166350738859143358">"Докоснете „Потвърждаване“ за завършване"</string>
- <!-- no translation found for biometric_dialog_tap_confirm_with_face (1597899891472340950) -->
- <skip />
+ <string name="biometric_dialog_tap_confirm_with_face" msgid="1597899891472340950">"Отключено чрез лицето ви. Натиснете, за да продължите."</string>
<string name="biometric_dialog_authenticated" msgid="7337147327545272484">"Удостоверено"</string>
<string name="biometric_dialog_use_pin" msgid="8385294115283000709">"Използване на ПИН"</string>
<string name="biometric_dialog_use_pattern" msgid="2315593393167211194">"Използване на фигура"</string>
@@ -462,8 +459,8 @@
<string name="wallet_secondary_label_device_locked" msgid="5175862019125370506">"Отключване с цел използване"</string>
<string name="wallet_error_generic" msgid="257704570182963611">"При извличането на картите ви възникна проблем. Моля, опитайте отново по-късно"</string>
<string name="wallet_lockscreen_settings_label" msgid="3539105300870383570">"Настройки за заключения екран"</string>
- <string name="qr_code_scanner_title" msgid="5660820608548306581">"QR код"</string>
- <string name="qr_code_scanner_description" msgid="7937603775306661863">"Докоснете за сканиране"</string>
+ <!-- no translation found for qr_code_scanner_title (5290201053875420785) -->
+ <skip />
<string name="status_bar_work" msgid="5238641949837091056">"Потребителски профил в Work"</string>
<string name="status_bar_airplane" msgid="4848702508684541009">"Самолетен режим"</string>
<string name="zen_alarm_warning" msgid="7844303238486849503">"Няма да чуете следващия си будилник в <xliff:g id="WHEN">%1$s</xliff:g>"</string>
@@ -827,6 +824,7 @@
<string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"Сдвояване на ново устройство"</string>
<string name="media_output_dialog_launch_app_text" msgid="1527413319632586259">"За да предавате тази сесия, моля, отворете приложението."</string>
<string name="media_output_dialog_unknown_launch_app_name" msgid="1084899329829371336">"Неизвестно приложение"</string>
+ <string name="media_output_dialog_button_stop_casting" msgid="6581379537930199189">"Спиране на предаването"</string>
<string name="build_number_clip_data_label" msgid="3623176728412560914">"Номер на компилацията"</string>
<string name="build_number_copy_toast" msgid="877720921605503046">"Номерът на компилацията е копиран в буферната памет."</string>
<string name="basic_status" msgid="2315371112182658176">"Отворен разговор"</string>
@@ -916,8 +914,6 @@
<string name="dream_overlay_status_bar_wifi_off" msgid="4497069245055003582">"Wi‑Fi не е налице"</string>
<string name="dream_overlay_status_bar_priority_mode" msgid="5428462123314728739">"Приоритетен режим"</string>
<string name="dream_overlay_status_bar_alarm_set" msgid="566707328356590886">"Будилникът е зададен"</string>
- <string name="dream_overlay_status_bar_assistant_guest_mode_enabled" msgid="3715897096012469615">"Режимът на гост за Асистент е активиран"</string>
<string name="dream_overlay_status_bar_camera_mic_off" msgid="3199425257833773569">"Камерата и микрофонът са изключени"</string>
- <!-- no translation found for dream_overlay_status_bar_notification_indicator (8091389255691081711) -->
- <skip />
+ <string name="dream_overlay_status_bar_notification_indicator" msgid="8091389255691081711">"{count,plural, =1{# известие}other{# известия}}"</string>
</resources>
diff --git a/packages/SystemUI/res/values-bn/strings.xml b/packages/SystemUI/res/values-bn/strings.xml
index b5040e9..2730b4c 100644
--- a/packages/SystemUI/res/values-bn/strings.xml
+++ b/packages/SystemUI/res/values-bn/strings.xml
@@ -20,19 +20,17 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_label" msgid="4811759950673118541">"সিস্টেম UI"</string>
- <!-- no translation found for battery_low_title (5319680173344341779) -->
- <skip />
- <!-- no translation found for battery_low_description (3282977755476423966) -->
- <skip />
- <!-- no translation found for battery_low_intro (5148725009653088790) -->
- <skip />
+ <string name="battery_low_title" msgid="5319680173344341779">"\'ব্যাটারি সেভার\' চালু করতে চান?"</string>
+ <string name="battery_low_description" msgid="3282977755476423966">"আপনার আর <xliff:g id="PERCENTAGE">%s</xliff:g> ব্যাটারি আছে। ব্যাটারি সেভার ডার্ক থিম চালু করে, ব্যাকগ্রাউন্ড অ্যাক্টিভিটি সীমিত করে এবং বিজ্ঞপ্তিতে দেরি করে।"</string>
+ <string name="battery_low_intro" msgid="5148725009653088790">"ব্যাটারি সেভার ডার্ক থিম চালু করে, ব্যাকগ্রাউন্ড অ্যাক্টিভিটি সীমিত করে এবং বিজ্ঞপ্তিতে দেরি করে।"</string>
<string name="battery_low_percent_format" msgid="4276661262843170964">"<xliff:g id="PERCENTAGE">%s</xliff:g> অবশিষ্ট আছে"</string>
<string name="invalid_charger_title" msgid="938685362320735167">"ইউএসবি দিয়ে চার্জ করা যাবে না"</string>
<string name="invalid_charger_text" msgid="2339310107232691577">"ডিভাইসের সাথে যে চার্জারটি পেয়েছেন, সেটি ব্যবহার করুন"</string>
<string name="battery_saver_confirmation_title" msgid="1234998463717398453">"ব্যাটারি সেভার চালু করবেন?"</string>
<string name="battery_saver_confirmation_title_generic" msgid="2299231884234959849">"ব্যাটারি সেভার সম্পর্কে"</string>
<string name="battery_saver_confirmation_ok" msgid="5042136476802816494">"চালু করুন"</string>
- <string name="battery_saver_start_action" msgid="4553256017945469937">"ব্যাটারি সেভার চালু করুন"</string>
+ <string name="battery_saver_start_action" msgid="8353766979886287140">"চালু করুন"</string>
+ <string name="battery_saver_dismiss_action" msgid="7199342621040014738">"না থাক"</string>
<string name="status_bar_settings_auto_rotation" msgid="8329080442278431708">"অটো-রোটেট স্ক্রিন"</string>
<string name="usb_device_permission_prompt" msgid="4414719028369181772">"<xliff:g id="APPLICATION">%1$s</xliff:g> কে <xliff:g id="USB_DEVICE">%2$s</xliff:g> অ্যাক্সেস করতে দেবেন?"</string>
<string name="usb_device_permission_prompt_warn" msgid="2309129784984063656">"<xliff:g id="USB_DEVICE">%2$s</xliff:g> অ্যাক্সেস করতে <xliff:g id="APPLICATION">%1$s</xliff:g>-কে কি অনুমতি দেবেন?\nএই অ্যাপকে রেকর্ড করার অনুমতি দেওয়া হয়নি কিন্তু USB ডিভাইসের মাধ্যমে সেটি অডিও রেকর্ড করতে পারে।"</string>
@@ -133,8 +131,7 @@
<string name="biometric_dialog_face_icon_description_authenticated" msgid="2242167416140740920">"ফেস যাচাই করা হয়েছে"</string>
<string name="biometric_dialog_face_icon_description_confirmed" msgid="7918067993953940778">"কনফার্ম করা হয়েছে"</string>
<string name="biometric_dialog_tap_confirm" msgid="9166350738859143358">"সম্পূর্ণ করতে \'কনফার্ম করুন\' বোতামে ট্যাপ করুন"</string>
- <!-- no translation found for biometric_dialog_tap_confirm_with_face (1597899891472340950) -->
- <skip />
+ <string name="biometric_dialog_tap_confirm_with_face" msgid="1597899891472340950">"আপনার মুখ মাধ্যমে আনলক করা হয়েছে। চালিয়ে যেতে প্রেস করুন।"</string>
<string name="biometric_dialog_authenticated" msgid="7337147327545272484">"প্রমাণীকৃত"</string>
<string name="biometric_dialog_use_pin" msgid="8385294115283000709">"পিন ব্যবহার করুন"</string>
<string name="biometric_dialog_use_pattern" msgid="2315593393167211194">"প্যাটার্ন ব্যবহার করুন"</string>
@@ -462,8 +459,8 @@
<string name="wallet_secondary_label_device_locked" msgid="5175862019125370506">"ব্যবহার করতে আনলক করুন"</string>
<string name="wallet_error_generic" msgid="257704570182963611">"আপনার কার্ড সংক্রান্ত তথ্য পেতে সমস্যা হয়েছে, পরে আবার চেষ্টা করুন"</string>
<string name="wallet_lockscreen_settings_label" msgid="3539105300870383570">"লক স্ক্রিন সেটিংস"</string>
- <string name="qr_code_scanner_title" msgid="5660820608548306581">"QR কোড"</string>
- <string name="qr_code_scanner_description" msgid="7937603775306661863">"স্ক্যান করতে ট্যাপ করুন"</string>
+ <!-- no translation found for qr_code_scanner_title (5290201053875420785) -->
+ <skip />
<string name="status_bar_work" msgid="5238641949837091056">"কাজের প্রোফাইল"</string>
<string name="status_bar_airplane" msgid="4848702508684541009">"বিমান মোড"</string>
<string name="zen_alarm_warning" msgid="7844303238486849503">"আপনি আপনার পরবর্তী <xliff:g id="WHEN">%1$s</xliff:g> অ্যালার্ম শুনতে পাবেন না"</string>
@@ -827,6 +824,7 @@
<string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"নতুন ডিভাইস পেয়ার করুন"</string>
<string name="media_output_dialog_launch_app_text" msgid="1527413319632586259">"এই সেশন কাস্ট করার জন্য, অ্যাপ খুলুন।"</string>
<string name="media_output_dialog_unknown_launch_app_name" msgid="1084899329829371336">"অজানা অ্যাপ"</string>
+ <string name="media_output_dialog_button_stop_casting" msgid="6581379537930199189">"কাস্ট করা বন্ধ করুন"</string>
<string name="build_number_clip_data_label" msgid="3623176728412560914">"বিল্ড নম্বর"</string>
<string name="build_number_copy_toast" msgid="877720921605503046">"বিল্ড নম্বর ক্লিপবোর্ডে কপি করা হয়েছে।"</string>
<string name="basic_status" msgid="2315371112182658176">"খোলা কথোপকথন"</string>
@@ -916,7 +914,6 @@
<string name="dream_overlay_status_bar_wifi_off" msgid="4497069245055003582">"ওয়াই-ফাই উপলভ্য নেই"</string>
<string name="dream_overlay_status_bar_priority_mode" msgid="5428462123314728739">"প্রায়োরিটি মোড"</string>
<string name="dream_overlay_status_bar_alarm_set" msgid="566707328356590886">"অ্যালার্ম সেট করা হয়েছে"</string>
- <string name="dream_overlay_status_bar_assistant_guest_mode_enabled" msgid="3715897096012469615">"Assistant-এর \'অতিথি মোড\' চালু করা হয়েছে"</string>
<string name="dream_overlay_status_bar_camera_mic_off" msgid="3199425257833773569">"ক্যামেরা ও মাইক্রোফোন বন্ধ আছে"</string>
<string name="dream_overlay_status_bar_notification_indicator" msgid="8091389255691081711">"{count,plural, =1{#টি বিজ্ঞপ্তি}one{#টি বিজ্ঞপ্তি}other{#টি বিজ্ঞপ্তি}}"</string>
</resources>
diff --git a/packages/SystemUI/res/values-bs/strings.xml b/packages/SystemUI/res/values-bs/strings.xml
index b0691fe..00973ee 100644
--- a/packages/SystemUI/res/values-bs/strings.xml
+++ b/packages/SystemUI/res/values-bs/strings.xml
@@ -20,19 +20,17 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_label" msgid="4811759950673118541">"Sistemski UI"</string>
- <!-- no translation found for battery_low_title (5319680173344341779) -->
- <skip />
- <!-- no translation found for battery_low_description (3282977755476423966) -->
- <skip />
- <!-- no translation found for battery_low_intro (5148725009653088790) -->
- <skip />
+ <string name="battery_low_title" msgid="5319680173344341779">"Uključiti Uštedu baterije?"</string>
+ <string name="battery_low_description" msgid="3282977755476423966">"Preostalo vam je još <xliff:g id="PERCENTAGE">%s</xliff:g> baterije. Ušteda baterije uključuje tamnu temu, ograničava aktivnost u pozadini i odgađa obavještenja."</string>
+ <string name="battery_low_intro" msgid="5148725009653088790">"Ušteda baterije uključuje tamnu temu, ograničava aktivnost u pozadini i odgađa obavještenja."</string>
<string name="battery_low_percent_format" msgid="4276661262843170964">"Preostalo <xliff:g id="PERCENTAGE">%s</xliff:g>"</string>
<string name="invalid_charger_title" msgid="938685362320735167">"Punjenje putem USB-a nije moguće"</string>
<string name="invalid_charger_text" msgid="2339310107232691577">"Koristite punjač koji ste dobili uz uređaj"</string>
<string name="battery_saver_confirmation_title" msgid="1234998463717398453">"Uključiti Uštedu baterije?"</string>
<string name="battery_saver_confirmation_title_generic" msgid="2299231884234959849">"Informacije o Uštedi baterije"</string>
<string name="battery_saver_confirmation_ok" msgid="5042136476802816494">"Uključi"</string>
- <string name="battery_saver_start_action" msgid="4553256017945469937">"Uključi Uštedu baterije"</string>
+ <string name="battery_saver_start_action" msgid="8353766979886287140">"Uključi"</string>
+ <string name="battery_saver_dismiss_action" msgid="7199342621040014738">"Ne, hvala"</string>
<string name="status_bar_settings_auto_rotation" msgid="8329080442278431708">"Automatsko rotiranje ekrana"</string>
<string name="usb_device_permission_prompt" msgid="4414719028369181772">"Dozvoliti aplikaciji <xliff:g id="APPLICATION">%1$s</xliff:g> pristup uređaju: <xliff:g id="USB_DEVICE">%2$s</xliff:g>?"</string>
<string name="usb_device_permission_prompt_warn" msgid="2309129784984063656">"Dozvoliti aplikaciji <xliff:g id="APPLICATION">%1$s</xliff:g> pristup uređaju <xliff:g id="USB_DEVICE">%2$s</xliff:g>?\nOvoj aplikaciji nije dato odobrenje za snimanje, ali može snimati zvuk putem ovog USB uređaja."</string>
@@ -133,8 +131,7 @@
<string name="biometric_dialog_face_icon_description_authenticated" msgid="2242167416140740920">"Lice je provjereno"</string>
<string name="biometric_dialog_face_icon_description_confirmed" msgid="7918067993953940778">"Potvrđeno"</string>
<string name="biometric_dialog_tap_confirm" msgid="9166350738859143358">"Dodirnite Potvrdi da završite"</string>
- <!-- no translation found for biometric_dialog_tap_confirm_with_face (1597899891472340950) -->
- <skip />
+ <string name="biometric_dialog_tap_confirm_with_face" msgid="1597899891472340950">"Otključano vašim licem. Pritisnite da nastavite."</string>
<string name="biometric_dialog_authenticated" msgid="7337147327545272484">"Autentificirano"</string>
<string name="biometric_dialog_use_pin" msgid="8385294115283000709">"Koristi PIN"</string>
<string name="biometric_dialog_use_pattern" msgid="2315593393167211194">"Koristi uzorak"</string>
@@ -465,8 +462,7 @@
<string name="wallet_secondary_label_device_locked" msgid="5175862019125370506">"Otključajte da koristite"</string>
<string name="wallet_error_generic" msgid="257704570182963611">"Došlo je do problema prilikom preuzimanja vaših kartica. Pokušajte ponovo kasnije"</string>
<string name="wallet_lockscreen_settings_label" msgid="3539105300870383570">"Postavke zaključavanja ekrana"</string>
- <string name="qr_code_scanner_title" msgid="5660820608548306581">"QR kôd"</string>
- <string name="qr_code_scanner_description" msgid="7937603775306661863">"Dodirnite da skenirate"</string>
+ <string name="qr_code_scanner_title" msgid="5290201053875420785">"Skeniraj QR kôd"</string>
<string name="status_bar_work" msgid="5238641949837091056">"Profil za posao"</string>
<string name="status_bar_airplane" msgid="4848702508684541009">"Način rada u avionu"</string>
<string name="zen_alarm_warning" msgid="7844303238486849503">"Nećete čuti sljedeći alarm u <xliff:g id="WHEN">%1$s</xliff:g>"</string>
@@ -833,6 +829,7 @@
<string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"Uparite novi uređaj"</string>
<string name="media_output_dialog_launch_app_text" msgid="1527413319632586259">"Da emitirate ovu sesiju, otvorite aplikaciju."</string>
<string name="media_output_dialog_unknown_launch_app_name" msgid="1084899329829371336">"Nepoznata aplikacija"</string>
+ <string name="media_output_dialog_button_stop_casting" msgid="6581379537930199189">"Zaustavi emitiranje"</string>
<string name="build_number_clip_data_label" msgid="3623176728412560914">"Broj verzije"</string>
<string name="build_number_copy_toast" msgid="877720921605503046">"Broj verzije je kopiran u međumemoriju."</string>
<string name="basic_status" msgid="2315371112182658176">"Otvoreni razgovor"</string>
@@ -923,7 +920,6 @@
<string name="dream_overlay_status_bar_wifi_off" msgid="4497069245055003582">"WiFi je nedostupan"</string>
<string name="dream_overlay_status_bar_priority_mode" msgid="5428462123314728739">"Način rada Prioriteti"</string>
<string name="dream_overlay_status_bar_alarm_set" msgid="566707328356590886">"Alarm je postavljen"</string>
- <string name="dream_overlay_status_bar_assistant_guest_mode_enabled" msgid="3715897096012469615">"Način rada za gosta Asistenta je omogućen"</string>
<string name="dream_overlay_status_bar_camera_mic_off" msgid="3199425257833773569">"Kamera i mikrofon su isključeni"</string>
- <string name="dream_overlay_status_bar_notification_indicator" msgid="8091389255691081711">"{count,plural, =1{# obavijest}one{# obavijest}few{# obavijesti}other{# obavijesti}}"</string>
+ <string name="dream_overlay_status_bar_notification_indicator" msgid="8091389255691081711">"{count,plural, =1{# obavještenje}one{# obavještenje}few{# obavještenja}other{# obavještenja}}"</string>
</resources>
diff --git a/packages/SystemUI/res/values-ca/strings.xml b/packages/SystemUI/res/values-ca/strings.xml
index da4cba7..975f4e0 100644
--- a/packages/SystemUI/res/values-ca/strings.xml
+++ b/packages/SystemUI/res/values-ca/strings.xml
@@ -20,19 +20,17 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_label" msgid="4811759950673118541">"IU del sistema"</string>
- <!-- no translation found for battery_low_title (5319680173344341779) -->
- <skip />
- <!-- no translation found for battery_low_description (3282977755476423966) -->
- <skip />
- <!-- no translation found for battery_low_intro (5148725009653088790) -->
- <skip />
+ <string name="battery_low_title" msgid="5319680173344341779">"Vols activar Estalvi de bateria?"</string>
+ <string name="battery_low_description" msgid="3282977755476423966">"Et queda un <xliff:g id="PERCENTAGE">%s</xliff:g> de bateria. Estalvi de bateria activa el tema fosc, restringeix l\'activitat en segon pla i endarrereix les notificacions."</string>
+ <string name="battery_low_intro" msgid="5148725009653088790">"Estalvi de bateria activa el tema fosc, restringeix l\'activitat en segon pla i endarrereix les notificacions."</string>
<string name="battery_low_percent_format" msgid="4276661262843170964">"Queda un <xliff:g id="PERCENTAGE">%s</xliff:g>."</string>
<string name="invalid_charger_title" msgid="938685362320735167">"No es pot carregar per USB"</string>
<string name="invalid_charger_text" msgid="2339310107232691577">"Fes servir el carregador original del dispositiu"</string>
<string name="battery_saver_confirmation_title" msgid="1234998463717398453">"Vols activar la funció Estalvi de bateria?"</string>
<string name="battery_saver_confirmation_title_generic" msgid="2299231884234959849">"Sobre la funció Estalvi de bateria"</string>
<string name="battery_saver_confirmation_ok" msgid="5042136476802816494">"Activa"</string>
- <string name="battery_saver_start_action" msgid="4553256017945469937">"Activa la funció Estalvi de bateria"</string>
+ <string name="battery_saver_start_action" msgid="8353766979886287140">"Activa"</string>
+ <string name="battery_saver_dismiss_action" msgid="7199342621040014738">"No, gràcies"</string>
<string name="status_bar_settings_auto_rotation" msgid="8329080442278431708">"Gira la pantalla automàticament"</string>
<string name="usb_device_permission_prompt" msgid="4414719028369181772">"Vols permetre que <xliff:g id="APPLICATION">%1$s</xliff:g> accedeixi a <xliff:g id="USB_DEVICE">%2$s</xliff:g>?"</string>
<string name="usb_device_permission_prompt_warn" msgid="2309129784984063656">"Vols permetre que <xliff:g id="APPLICATION">%1$s</xliff:g> accedeixi a <xliff:g id="USB_DEVICE">%2$s</xliff:g>?\nAquesta aplicació no té permís de gravació, però pot capturar àudio a través d\'aquest dispositiu USB."</string>
@@ -133,8 +131,7 @@
<string name="biometric_dialog_face_icon_description_authenticated" msgid="2242167416140740920">"Cara autenticada"</string>
<string name="biometric_dialog_face_icon_description_confirmed" msgid="7918067993953940778">"Confirmat"</string>
<string name="biometric_dialog_tap_confirm" msgid="9166350738859143358">"Toca Confirma per completar"</string>
- <!-- no translation found for biometric_dialog_tap_confirm_with_face (1597899891472340950) -->
- <skip />
+ <string name="biometric_dialog_tap_confirm_with_face" msgid="1597899891472340950">"S\'ha desbloquejat amb la cara. Prem per continuar."</string>
<string name="biometric_dialog_authenticated" msgid="7337147327545272484">"Autenticat"</string>
<string name="biometric_dialog_use_pin" msgid="8385294115283000709">"Utilitza el PIN"</string>
<string name="biometric_dialog_use_pattern" msgid="2315593393167211194">"Utilitza el patró"</string>
@@ -462,8 +459,8 @@
<string name="wallet_secondary_label_device_locked" msgid="5175862019125370506">"Desbloqueja per utilitzar"</string>
<string name="wallet_error_generic" msgid="257704570182963611">"Hi ha hagut un problema en obtenir les teves targetes; torna-ho a provar més tard"</string>
<string name="wallet_lockscreen_settings_label" msgid="3539105300870383570">"Configuració de la pantalla de bloqueig"</string>
- <string name="qr_code_scanner_title" msgid="5660820608548306581">"Codi QR"</string>
- <string name="qr_code_scanner_description" msgid="7937603775306661863">"Toca per escanejar"</string>
+ <!-- no translation found for qr_code_scanner_title (5290201053875420785) -->
+ <skip />
<string name="status_bar_work" msgid="5238641949837091056">"Perfil de treball"</string>
<string name="status_bar_airplane" msgid="4848702508684541009">"Mode d\'avió"</string>
<string name="zen_alarm_warning" msgid="7844303238486849503">"<xliff:g id="WHEN">%1$s</xliff:g> no sentiràs la pròxima alarma"</string>
@@ -827,6 +824,7 @@
<string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"Vincula un dispositiu nou"</string>
<string name="media_output_dialog_launch_app_text" msgid="1527413319632586259">"Per emetre aquesta sessió, obre l\'aplicació."</string>
<string name="media_output_dialog_unknown_launch_app_name" msgid="1084899329829371336">"Aplicació desconeguda"</string>
+ <string name="media_output_dialog_button_stop_casting" msgid="6581379537930199189">"Atura l\'emissió"</string>
<string name="build_number_clip_data_label" msgid="3623176728412560914">"Número de compilació"</string>
<string name="build_number_copy_toast" msgid="877720921605503046">"El número de compilació s\'ha copiat al porta-retalls."</string>
<string name="basic_status" msgid="2315371112182658176">"Conversa oberta"</string>
@@ -916,8 +914,6 @@
<string name="dream_overlay_status_bar_wifi_off" msgid="4497069245055003582">"Wi‑Fi no disponible"</string>
<string name="dream_overlay_status_bar_priority_mode" msgid="5428462123314728739">"Mode Prioritat"</string>
<string name="dream_overlay_status_bar_alarm_set" msgid="566707328356590886">"Alarma definida"</string>
- <string name="dream_overlay_status_bar_assistant_guest_mode_enabled" msgid="3715897096012469615">"Mode de convidat de l\'Assistent activat"</string>
<string name="dream_overlay_status_bar_camera_mic_off" msgid="3199425257833773569">"Càmera i micròfon desactivats"</string>
- <!-- no translation found for dream_overlay_status_bar_notification_indicator (8091389255691081711) -->
- <skip />
+ <string name="dream_overlay_status_bar_notification_indicator" msgid="8091389255691081711">"{count,plural, =1{# notificació}other{# notificacions}}"</string>
</resources>
diff --git a/packages/SystemUI/res/values-cs/strings.xml b/packages/SystemUI/res/values-cs/strings.xml
index e93fc29..ee9a04f 100644
--- a/packages/SystemUI/res/values-cs/strings.xml
+++ b/packages/SystemUI/res/values-cs/strings.xml
@@ -20,19 +20,17 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_label" msgid="4811759950673118541">"UI systému"</string>
- <!-- no translation found for battery_low_title (5319680173344341779) -->
- <skip />
- <!-- no translation found for battery_low_description (3282977755476423966) -->
- <skip />
- <!-- no translation found for battery_low_intro (5148725009653088790) -->
- <skip />
+ <string name="battery_low_title" msgid="5319680173344341779">"Zapnout spořič baterie?"</string>
+ <string name="battery_low_description" msgid="3282977755476423966">"Zbývá <xliff:g id="PERCENTAGE">%s</xliff:g> baterie. Spořič baterie zapne tmavý motiv, omezí aktivitu na pozadí a pozdrží oznámení."</string>
+ <string name="battery_low_intro" msgid="5148725009653088790">"Spořič baterie zapne tmavý motiv, omezí aktivitu na pozadí a pozdrží oznámení."</string>
<string name="battery_low_percent_format" msgid="4276661262843170964">"Zbývá <xliff:g id="PERCENTAGE">%s</xliff:g>"</string>
<string name="invalid_charger_title" msgid="938685362320735167">"Nabíjení přes USB nefunguje"</string>
<string name="invalid_charger_text" msgid="2339310107232691577">"Používejte originální nabíječku, která byla dodána spolu se zařízením."</string>
<string name="battery_saver_confirmation_title" msgid="1234998463717398453">"Zapnout spořič baterie?"</string>
<string name="battery_saver_confirmation_title_generic" msgid="2299231884234959849">"Informace o spořiči baterie"</string>
<string name="battery_saver_confirmation_ok" msgid="5042136476802816494">"Zapnout"</string>
- <string name="battery_saver_start_action" msgid="4553256017945469937">"Zapnout spořič baterie"</string>
+ <string name="battery_saver_start_action" msgid="8353766979886287140">"Zapnout"</string>
+ <string name="battery_saver_dismiss_action" msgid="7199342621040014738">"Ne, díky"</string>
<string name="status_bar_settings_auto_rotation" msgid="8329080442278431708">"Automatické otočení obrazovky"</string>
<string name="usb_device_permission_prompt" msgid="4414719028369181772">"Povolit aplikaci <xliff:g id="APPLICATION">%1$s</xliff:g> přístup k zařízení <xliff:g id="USB_DEVICE">%2$s</xliff:g>?"</string>
<string name="usb_device_permission_prompt_warn" msgid="2309129784984063656">"Povolit aplikaci <xliff:g id="APPLICATION">%1$s</xliff:g> přístup k zařízení <xliff:g id="USB_DEVICE">%2$s</xliff:g>?\nTato aplikace nemá oprávnění k nahrávání, ale může zaznamenávat zvuk prostřednictvím tohoto zařízení USB."</string>
@@ -133,8 +131,7 @@
<string name="biometric_dialog_face_icon_description_authenticated" msgid="2242167416140740920">"Obličej byl ověřen"</string>
<string name="biometric_dialog_face_icon_description_confirmed" msgid="7918067993953940778">"Potvrzeno"</string>
<string name="biometric_dialog_tap_confirm" msgid="9166350738859143358">"Ověření dokončíte klepnutím na Potvrdit"</string>
- <!-- no translation found for biometric_dialog_tap_confirm_with_face (1597899891472340950) -->
- <skip />
+ <string name="biometric_dialog_tap_confirm_with_face" msgid="1597899891472340950">"Odemyká se obličejem. Pokračujte stisknutím."</string>
<string name="biometric_dialog_authenticated" msgid="7337147327545272484">"Ověřeno"</string>
<string name="biometric_dialog_use_pin" msgid="8385294115283000709">"Použít kód PIN"</string>
<string name="biometric_dialog_use_pattern" msgid="2315593393167211194">"Použít gesto"</string>
@@ -468,8 +465,8 @@
<string name="wallet_secondary_label_device_locked" msgid="5175862019125370506">"Odemknout a použít"</string>
<string name="wallet_error_generic" msgid="257704570182963611">"Při načítání karet došlo k problému, zkuste to později"</string>
<string name="wallet_lockscreen_settings_label" msgid="3539105300870383570">"Nastavení obrazovky uzamčení"</string>
- <string name="qr_code_scanner_title" msgid="5660820608548306581">"QR kód"</string>
- <string name="qr_code_scanner_description" msgid="7937603775306661863">"Klepnutím naskenujete kód"</string>
+ <!-- no translation found for qr_code_scanner_title (5290201053875420785) -->
+ <skip />
<string name="status_bar_work" msgid="5238641949837091056">"Pracovní profil"</string>
<string name="status_bar_airplane" msgid="4848702508684541009">"Režim Letadlo"</string>
<string name="zen_alarm_warning" msgid="7844303238486849503">"Svůj další budík <xliff:g id="WHEN">%1$s</xliff:g> neuslyšíte"</string>
@@ -839,6 +836,7 @@
<string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"Spárovat nové zařízení"</string>
<string name="media_output_dialog_launch_app_text" msgid="1527413319632586259">"Pokud chcete odesílat relaci, otevřete aplikaci."</string>
<string name="media_output_dialog_unknown_launch_app_name" msgid="1084899329829371336">"Neznámá aplikace"</string>
+ <string name="media_output_dialog_button_stop_casting" msgid="6581379537930199189">"Zastavit odesílání"</string>
<string name="build_number_clip_data_label" msgid="3623176728412560914">"Číslo sestavení"</string>
<string name="build_number_copy_toast" msgid="877720921605503046">"Číslo sestavení bylo zkopírováno do schránky."</string>
<string name="basic_status" msgid="2315371112182658176">"Otevřít konverzaci"</string>
@@ -930,7 +928,6 @@
<string name="dream_overlay_status_bar_wifi_off" msgid="4497069245055003582">"Síť Wi‑Fi není k dispozici"</string>
<string name="dream_overlay_status_bar_priority_mode" msgid="5428462123314728739">"Prioritní režim"</string>
<string name="dream_overlay_status_bar_alarm_set" msgid="566707328356590886">"Je nastaven budík"</string>
- <string name="dream_overlay_status_bar_assistant_guest_mode_enabled" msgid="3715897096012469615">"U Asistenta je aktivován režim hosta"</string>
<string name="dream_overlay_status_bar_camera_mic_off" msgid="3199425257833773569">"Fotoaparát a mikrofon jsou vypnuté"</string>
<string name="dream_overlay_status_bar_notification_indicator" msgid="8091389255691081711">"{count,plural, =1{# oznámení}few{# oznámení}many{# oznámení}other{# oznámení}}"</string>
</resources>
diff --git a/packages/SystemUI/res/values-da/strings.xml b/packages/SystemUI/res/values-da/strings.xml
index bf460fe..43027b8 100644
--- a/packages/SystemUI/res/values-da/strings.xml
+++ b/packages/SystemUI/res/values-da/strings.xml
@@ -20,19 +20,17 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_label" msgid="4811759950673118541">"System-UI"</string>
- <!-- no translation found for battery_low_title (5319680173344341779) -->
- <skip />
- <!-- no translation found for battery_low_description (3282977755476423966) -->
- <skip />
- <!-- no translation found for battery_low_intro (5148725009653088790) -->
- <skip />
+ <string name="battery_low_title" msgid="5319680173344341779">"Vil du aktivere Batterisparefunktion?"</string>
+ <string name="battery_low_description" msgid="3282977755476423966">"Du har <xliff:g id="PERCENTAGE">%s</xliff:g> batteri tilbage. Batterisparefunktion aktiverer Mørkt tema, begrænser aktivitet i baggrunden og udskyder notifikationer."</string>
+ <string name="battery_low_intro" msgid="5148725009653088790">"Batterisparefunktion aktiverer Mørkt tema, begrænser aktivitet i baggrunden og udskyder notifikationer."</string>
<string name="battery_low_percent_format" msgid="4276661262843170964">"<xliff:g id="PERCENTAGE">%s</xliff:g> tilbage"</string>
<string name="invalid_charger_title" msgid="938685362320735167">"Enheden kan ikke oplades via USB"</string>
<string name="invalid_charger_text" msgid="2339310107232691577">"Brug den oplader, der fulgte med din enhed"</string>
<string name="battery_saver_confirmation_title" msgid="1234998463717398453">"Vil du aktivere Batterisparefunktion?"</string>
<string name="battery_saver_confirmation_title_generic" msgid="2299231884234959849">"Om Batterisparefunktion"</string>
<string name="battery_saver_confirmation_ok" msgid="5042136476802816494">"Aktivér"</string>
- <string name="battery_saver_start_action" msgid="4553256017945469937">"Aktivér batterisparefunktion"</string>
+ <string name="battery_saver_start_action" msgid="8353766979886287140">"Aktivér"</string>
+ <string name="battery_saver_dismiss_action" msgid="7199342621040014738">"Nej tak"</string>
<string name="status_bar_settings_auto_rotation" msgid="8329080442278431708">"Roter skærm automatisk"</string>
<string name="usb_device_permission_prompt" msgid="4414719028369181772">"Vil du give <xliff:g id="APPLICATION">%1$s</xliff:g> adgang til <xliff:g id="USB_DEVICE">%2$s</xliff:g>?"</string>
<string name="usb_device_permission_prompt_warn" msgid="2309129784984063656">"Vil du give <xliff:g id="APPLICATION">%1$s</xliff:g> adgang til <xliff:g id="USB_DEVICE">%2$s</xliff:g>?\nDenne app har ikke fået tilladelse til at optage, men optager muligvis lyd via denne USB-enhed."</string>
@@ -133,8 +131,7 @@
<string name="biometric_dialog_face_icon_description_authenticated" msgid="2242167416140740920">"Ansigtet er godkendt"</string>
<string name="biometric_dialog_face_icon_description_confirmed" msgid="7918067993953940778">"Bekræftet"</string>
<string name="biometric_dialog_tap_confirm" msgid="9166350738859143358">"Tryk på Bekræft for at udføre"</string>
- <!-- no translation found for biometric_dialog_tap_confirm_with_face (1597899891472340950) -->
- <skip />
+ <string name="biometric_dialog_tap_confirm_with_face" msgid="1597899891472340950">"Låst op med ansigtsgenkendelse. Tryk for at fortsætte."</string>
<string name="biometric_dialog_authenticated" msgid="7337147327545272484">"Godkendt"</string>
<string name="biometric_dialog_use_pin" msgid="8385294115283000709">"Brug pinkode"</string>
<string name="biometric_dialog_use_pattern" msgid="2315593393167211194">"Brug mønster"</string>
@@ -462,8 +459,8 @@
<string name="wallet_secondary_label_device_locked" msgid="5175862019125370506">"Lås op for at bruge"</string>
<string name="wallet_error_generic" msgid="257704570182963611">"Dine kort kunne ikke hentes. Prøv igen senere."</string>
<string name="wallet_lockscreen_settings_label" msgid="3539105300870383570">"Lås skærmindstillinger"</string>
- <string name="qr_code_scanner_title" msgid="5660820608548306581">"QR-kode"</string>
- <string name="qr_code_scanner_description" msgid="7937603775306661863">"Tryk for at scanne"</string>
+ <!-- no translation found for qr_code_scanner_title (5290201053875420785) -->
+ <skip />
<string name="status_bar_work" msgid="5238641949837091056">"Arbejdsprofil"</string>
<string name="status_bar_airplane" msgid="4848702508684541009">"Flytilstand"</string>
<string name="zen_alarm_warning" msgid="7844303238486849503">"Du vil ikke kunne høre din næste alarm <xliff:g id="WHEN">%1$s</xliff:g>"</string>
@@ -827,6 +824,7 @@
<string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"Par ny enhed"</string>
<string name="media_output_dialog_launch_app_text" msgid="1527413319632586259">"Åbn appen for at caste denne session."</string>
<string name="media_output_dialog_unknown_launch_app_name" msgid="1084899329829371336">"Ukendt app"</string>
+ <string name="media_output_dialog_button_stop_casting" msgid="6581379537930199189">"Stop med at caste"</string>
<string name="build_number_clip_data_label" msgid="3623176728412560914">"Buildnummer"</string>
<string name="build_number_copy_toast" msgid="877720921605503046">"Buildnummeret blev kopieret til udklipsholderen."</string>
<string name="basic_status" msgid="2315371112182658176">"Åben samtale"</string>
@@ -916,8 +914,6 @@
<string name="dream_overlay_status_bar_wifi_off" msgid="4497069245055003582">"Ingen tilgængelig Wi-Fi-forbindelse"</string>
<string name="dream_overlay_status_bar_priority_mode" msgid="5428462123314728739">"Tilstanden Prioritet"</string>
<string name="dream_overlay_status_bar_alarm_set" msgid="566707328356590886">"Alarmen er indstillet"</string>
- <string name="dream_overlay_status_bar_assistant_guest_mode_enabled" msgid="3715897096012469615">"Gæstetilstand i Assistent er aktiveret"</string>
<string name="dream_overlay_status_bar_camera_mic_off" msgid="3199425257833773569">"Kamera og mikrofon er slået fra"</string>
- <!-- no translation found for dream_overlay_status_bar_notification_indicator (8091389255691081711) -->
- <skip />
+ <string name="dream_overlay_status_bar_notification_indicator" msgid="8091389255691081711">"{count,plural, =1{# notifikation}one{# notifikation}other{# notifikationer}}"</string>
</resources>
diff --git a/packages/SystemUI/res/values-de/strings.xml b/packages/SystemUI/res/values-de/strings.xml
index 6197b3f..60bcecb 100644
--- a/packages/SystemUI/res/values-de/strings.xml
+++ b/packages/SystemUI/res/values-de/strings.xml
@@ -20,19 +20,17 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_label" msgid="4811759950673118541">"System-UI"</string>
- <!-- no translation found for battery_low_title (5319680173344341779) -->
- <skip />
- <!-- no translation found for battery_low_description (3282977755476423966) -->
- <skip />
- <!-- no translation found for battery_low_intro (5148725009653088790) -->
- <skip />
+ <string name="battery_low_title" msgid="5319680173344341779">"Energiesparmodus aktivieren?"</string>
+ <string name="battery_low_description" msgid="3282977755476423966">"Dein Akkustand beträgt <xliff:g id="PERCENTAGE">%s</xliff:g>. Im Energiesparmodus wird das dunkle Design aktiviert und es werden Hintergrundaktivitäten eingeschränkt sowie Benachrichtigungen verzögert empfangen."</string>
+ <string name="battery_low_intro" msgid="5148725009653088790">"Im Energiesparmodus wird das dunkle Design aktiviert und es werden Hintergrundaktivitäten eingeschränkt sowie Benachrichtigungen verzögert empfangen."</string>
<string name="battery_low_percent_format" msgid="4276661262843170964">"<xliff:g id="PERCENTAGE">%s</xliff:g> verbleibend"</string>
<string name="invalid_charger_title" msgid="938685362320735167">"Aufladen über USB nicht möglich"</string>
<string name="invalid_charger_text" msgid="2339310107232691577">"Verwende das mit dem Gerät gelieferte Ladegerät"</string>
<string name="battery_saver_confirmation_title" msgid="1234998463717398453">"Energiesparmodus aktivieren?"</string>
<string name="battery_saver_confirmation_title_generic" msgid="2299231884234959849">"Über den Energiesparmodus"</string>
<string name="battery_saver_confirmation_ok" msgid="5042136476802816494">"Aktivieren"</string>
- <string name="battery_saver_start_action" msgid="4553256017945469937">"Energiesparmodus aktivieren"</string>
+ <string name="battery_saver_start_action" msgid="8353766979886287140">"Aktivieren"</string>
+ <string name="battery_saver_dismiss_action" msgid="7199342621040014738">"Nein danke"</string>
<string name="status_bar_settings_auto_rotation" msgid="8329080442278431708">"Bildschirm automatisch drehen"</string>
<string name="usb_device_permission_prompt" msgid="4414719028369181772">"<xliff:g id="APPLICATION">%1$s</xliff:g> den Zugriff auf <xliff:g id="USB_DEVICE">%2$s</xliff:g> gewähren?"</string>
<string name="usb_device_permission_prompt_warn" msgid="2309129784984063656">"<xliff:g id="APPLICATION">%1$s</xliff:g> den Zugriff auf <xliff:g id="USB_DEVICE">%2$s</xliff:g> gewähren?\nDiese App hat noch nicht die Berechtigung zum Aufnehmen erhalten, könnte jedoch Audio über dieses USB-Gerät aufnehmen."</string>
@@ -133,8 +131,7 @@
<string name="biometric_dialog_face_icon_description_authenticated" msgid="2242167416140740920">"Gesicht authentifiziert"</string>
<string name="biometric_dialog_face_icon_description_confirmed" msgid="7918067993953940778">"Bestätigt"</string>
<string name="biometric_dialog_tap_confirm" msgid="9166350738859143358">"Zum Abschließen auf \"Bestätigen\" tippen"</string>
- <!-- no translation found for biometric_dialog_tap_confirm_with_face (1597899891472340950) -->
- <skip />
+ <string name="biometric_dialog_tap_confirm_with_face" msgid="1597899891472340950">"Mit dem Gesicht entsperrt. Drücken, um fortzufahren."</string>
<string name="biometric_dialog_authenticated" msgid="7337147327545272484">"Authentifiziert"</string>
<string name="biometric_dialog_use_pin" msgid="8385294115283000709">"PIN verwenden"</string>
<string name="biometric_dialog_use_pattern" msgid="2315593393167211194">"Muster verwenden"</string>
@@ -462,8 +459,8 @@
<string name="wallet_secondary_label_device_locked" msgid="5175862019125370506">"Zum Verwenden entsperren"</string>
<string name="wallet_error_generic" msgid="257704570182963611">"Beim Abrufen deiner Karten ist ein Fehler aufgetreten – bitte versuch es später noch einmal"</string>
<string name="wallet_lockscreen_settings_label" msgid="3539105300870383570">"Einstellungen für den Sperrbildschirm"</string>
- <string name="qr_code_scanner_title" msgid="5660820608548306581">"QR-Code"</string>
- <string name="qr_code_scanner_description" msgid="7937603775306661863">"Zum Scannen tippen"</string>
+ <!-- no translation found for qr_code_scanner_title (5290201053875420785) -->
+ <skip />
<string name="status_bar_work" msgid="5238641949837091056">"Arbeitsprofil"</string>
<string name="status_bar_airplane" msgid="4848702508684541009">"Flugmodus"</string>
<string name="zen_alarm_warning" msgid="7844303238486849503">"Lautloser Weckruf <xliff:g id="WHEN">%1$s</xliff:g>"</string>
@@ -686,7 +683,7 @@
<string name="notification_channel_general" msgid="4384774889645929705">"Nachrichten"</string>
<string name="notification_channel_storage" msgid="2720725707628094977">"Speicher"</string>
<string name="notification_channel_hints" msgid="7703783206000346876">"Hinweise"</string>
- <string name="instant_apps" msgid="8337185853050247304">"Instant-Apps"</string>
+ <string name="instant_apps" msgid="8337185853050247304">"Instant Apps"</string>
<string name="instant_apps_title" msgid="8942706782103036910">"<xliff:g id="APP">%1$s</xliff:g> wird ausgeführt"</string>
<string name="instant_apps_message" msgid="6112428971833011754">"App wurde geöffnet, ohne vorher installiert zu werden."</string>
<string name="instant_apps_message_with_help" msgid="1816952263531203932">"App wurde geöffnet, ohne vorher installiert zu werden. Tippe, um weitere Informationen zu erhalten."</string>
@@ -827,6 +824,7 @@
<string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"Neues Gerät koppeln"</string>
<string name="media_output_dialog_launch_app_text" msgid="1527413319632586259">"Öffne zum Streamen dieser Sitzung die App."</string>
<string name="media_output_dialog_unknown_launch_app_name" msgid="1084899329829371336">"Unbekannte App"</string>
+ <string name="media_output_dialog_button_stop_casting" msgid="6581379537930199189">"Streaming beenden"</string>
<string name="build_number_clip_data_label" msgid="3623176728412560914">"Build-Nummer"</string>
<string name="build_number_copy_toast" msgid="877720921605503046">"Build-Nummer in Zwischenablage kopiert."</string>
<string name="basic_status" msgid="2315371112182658176">"Offene Unterhaltung"</string>
@@ -916,8 +914,6 @@
<string name="dream_overlay_status_bar_wifi_off" msgid="4497069245055003582">"WLAN nicht verfügbar"</string>
<string name="dream_overlay_status_bar_priority_mode" msgid="5428462123314728739">"Prioritätsmodus"</string>
<string name="dream_overlay_status_bar_alarm_set" msgid="566707328356590886">"Wecker gestellt"</string>
- <string name="dream_overlay_status_bar_assistant_guest_mode_enabled" msgid="3715897096012469615">"Assistant-Gastmodus aktiviert"</string>
<string name="dream_overlay_status_bar_camera_mic_off" msgid="3199425257833773569">"Kamera und Mikrofon ausgeschaltet"</string>
- <!-- no translation found for dream_overlay_status_bar_notification_indicator (8091389255691081711) -->
- <skip />
+ <string name="dream_overlay_status_bar_notification_indicator" msgid="8091389255691081711">"{count,plural, =1{# Benachrichtigung}other{# Benachrichtigungen}}"</string>
</resources>
diff --git a/packages/SystemUI/res/values-el/strings.xml b/packages/SystemUI/res/values-el/strings.xml
index dc0d98b..17a54c2 100644
--- a/packages/SystemUI/res/values-el/strings.xml
+++ b/packages/SystemUI/res/values-el/strings.xml
@@ -20,19 +20,17 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_label" msgid="4811759950673118541">"UI συστήματ."</string>
- <!-- no translation found for battery_low_title (5319680173344341779) -->
- <skip />
- <!-- no translation found for battery_low_description (3282977755476423966) -->
- <skip />
- <!-- no translation found for battery_low_intro (5148725009653088790) -->
- <skip />
+ <string name="battery_low_title" msgid="5319680173344341779">"Ενεργοποίηση Εξοικονόμησης μπαταρίας;"</string>
+ <string name="battery_low_description" msgid="3282977755476423966">"Απομένει <xliff:g id="PERCENTAGE">%s</xliff:g> μπαταρία. Η Εξοικονόμηση μπαταρίας ενεργοποιεί το Σκούρο θέμα, περιορίζει τη δραστηριότητα στο παρασκήνιο και καθυστερεί τις ειδοποιήσεις."</string>
+ <string name="battery_low_intro" msgid="5148725009653088790">"Η Εξοικονόμηση μπαταρίας ενεργοποιεί το Σκούρο θέμα, περιορίζει τη δραστηριότητα στο παρασκήνιο και καθυστερεί τις ειδοποιήσεις."</string>
<string name="battery_low_percent_format" msgid="4276661262843170964">"Απομένουν <xliff:g id="PERCENTAGE">%s</xliff:g>"</string>
<string name="invalid_charger_title" msgid="938685362320735167">"Δεν είναι δυνατή η φόρτιση μέσω USB"</string>
<string name="invalid_charger_text" msgid="2339310107232691577">"Χρησιμοποιήστε τον φορτιστή που συνοδεύει τη συσκευή σας"</string>
<string name="battery_saver_confirmation_title" msgid="1234998463717398453">"Να ενεργοποιηθεί η Εξοικονόμηση μπαταρίας;"</string>
<string name="battery_saver_confirmation_title_generic" msgid="2299231884234959849">"Σχετικά με την Εξοικονόμηση μπαταρίας"</string>
<string name="battery_saver_confirmation_ok" msgid="5042136476802816494">"Ενεργοποίηση"</string>
- <string name="battery_saver_start_action" msgid="4553256017945469937">"Ενεργοποίηση Εξοικονόμησης μπαταρίας"</string>
+ <string name="battery_saver_start_action" msgid="8353766979886287140">"Ενεργοποίηση"</string>
+ <string name="battery_saver_dismiss_action" msgid="7199342621040014738">"Όχι, ευχαριστώ"</string>
<string name="status_bar_settings_auto_rotation" msgid="8329080442278431708">"Αυτόματη περιστροφή οθόνης"</string>
<string name="usb_device_permission_prompt" msgid="4414719028369181772">"Να επιτρέπεται η πρόσβαση της εφαρμογής <xliff:g id="APPLICATION">%1$s</xliff:g> στη συσκευή <xliff:g id="USB_DEVICE">%2$s</xliff:g>;"</string>
<string name="usb_device_permission_prompt_warn" msgid="2309129784984063656">"Να επιτρέπεται στην εφαρμογή <xliff:g id="APPLICATION">%1$s</xliff:g> να έχει πρόσβαση στη συσκευή <xliff:g id="USB_DEVICE">%2$s</xliff:g>;\nΔεν έχει εκχωρηθεί άδεια εγγραφής σε αυτήν την εφαρμογή, αλλά μέσω αυτής της συσκευής USB θα μπορεί να εγγράφει ήχο."</string>
@@ -133,8 +131,7 @@
<string name="biometric_dialog_face_icon_description_authenticated" msgid="2242167416140740920">"Έγινε έλεγχος ταυτότητας προσώπου"</string>
<string name="biometric_dialog_face_icon_description_confirmed" msgid="7918067993953940778">"Επιβεβαιώθηκε"</string>
<string name="biometric_dialog_tap_confirm" msgid="9166350738859143358">"Πατήστε Επιβεβαίωση για ολοκλήρωση"</string>
- <!-- no translation found for biometric_dialog_tap_confirm_with_face (1597899891472340950) -->
- <skip />
+ <string name="biometric_dialog_tap_confirm_with_face" msgid="1597899891472340950">"Ξεκλειδώθηκε με το πρόσωπό σας. Πατήστε για συνέχεια."</string>
<string name="biometric_dialog_authenticated" msgid="7337147327545272484">"Ολοκληρώθηκε ο έλεγχος ταυτότητας"</string>
<string name="biometric_dialog_use_pin" msgid="8385294115283000709">"Χρήση PIN"</string>
<string name="biometric_dialog_use_pattern" msgid="2315593393167211194">"Χρήση μοτίβου"</string>
@@ -462,8 +459,8 @@
<string name="wallet_secondary_label_device_locked" msgid="5175862019125370506">"Ξεκλείδωμα για χρήση"</string>
<string name="wallet_error_generic" msgid="257704570182963611">"Παρουσιάστηκε πρόβλημα με τη λήψη των καρτών σας. Δοκιμάστε ξανά αργότερα"</string>
<string name="wallet_lockscreen_settings_label" msgid="3539105300870383570">"Ρυθμίσεις κλειδώματος οθόνης"</string>
- <string name="qr_code_scanner_title" msgid="5660820608548306581">"Κωδικός QR"</string>
- <string name="qr_code_scanner_description" msgid="7937603775306661863">"Πατήστε για σάρωση"</string>
+ <!-- no translation found for qr_code_scanner_title (5290201053875420785) -->
+ <skip />
<string name="status_bar_work" msgid="5238641949837091056">"Προφίλ εργασίας"</string>
<string name="status_bar_airplane" msgid="4848702508684541009">"Λειτουργία πτήσης"</string>
<string name="zen_alarm_warning" msgid="7844303238486849503">"Δεν θα ακούσετε το επόμενο ξυπνητήρι σας <xliff:g id="WHEN">%1$s</xliff:g>"</string>
@@ -827,6 +824,7 @@
<string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"Σύζευξη νέας συσκευής"</string>
<string name="media_output_dialog_launch_app_text" msgid="1527413319632586259">"Για μετάδοση της περιόδου σύνδεσης, ανοίξτε την εφαρμογή."</string>
<string name="media_output_dialog_unknown_launch_app_name" msgid="1084899329829371336">"Άγνωστη εφαρμογή"</string>
+ <string name="media_output_dialog_button_stop_casting" msgid="6581379537930199189">"Διακοπή μετάδοσης"</string>
<string name="build_number_clip_data_label" msgid="3623176728412560914">"Αριθμός έκδοσης"</string>
<string name="build_number_copy_toast" msgid="877720921605503046">"Ο αριθμός έκδοσης αντιγράφηκε στο πρόχειρο."</string>
<string name="basic_status" msgid="2315371112182658176">"Άνοιγμα συνομιλίας"</string>
@@ -916,7 +914,6 @@
<string name="dream_overlay_status_bar_wifi_off" msgid="4497069245055003582">"Το Wi‑Fi δεν είναι διαθέσιμο"</string>
<string name="dream_overlay_status_bar_priority_mode" msgid="5428462123314728739">"Λειτουργία προτεραιότητας"</string>
<string name="dream_overlay_status_bar_alarm_set" msgid="566707328356590886">"Το ξυπνητήρι ρυθμίστηκε"</string>
- <string name="dream_overlay_status_bar_assistant_guest_mode_enabled" msgid="3715897096012469615">"Η λειτουργία επισκέπτη του Βοηθού ενεργοποιήθηκε"</string>
<string name="dream_overlay_status_bar_camera_mic_off" msgid="3199425257833773569">"Η κάμερα και το μικρόφωνο έχουν απενεργοποιηθεί"</string>
<string name="dream_overlay_status_bar_notification_indicator" msgid="8091389255691081711">"{count,plural, =1{# ειδοποίηση}other{# ειδοποιήσεις}}"</string>
</resources>
diff --git a/packages/SystemUI/res/values-en-rAU/strings.xml b/packages/SystemUI/res/values-en-rAU/strings.xml
index fcbe0a6..5544a95 100644
--- a/packages/SystemUI/res/values-en-rAU/strings.xml
+++ b/packages/SystemUI/res/values-en-rAU/strings.xml
@@ -29,7 +29,8 @@
<string name="battery_saver_confirmation_title" msgid="1234998463717398453">"Turn on Battery Saver?"</string>
<string name="battery_saver_confirmation_title_generic" msgid="2299231884234959849">"About Battery Saver"</string>
<string name="battery_saver_confirmation_ok" msgid="5042136476802816494">"Turn on"</string>
- <string name="battery_saver_start_action" msgid="4553256017945469937">"Turn on Battery Saver"</string>
+ <string name="battery_saver_start_action" msgid="8353766979886287140">"Turn on"</string>
+ <string name="battery_saver_dismiss_action" msgid="7199342621040014738">"No thanks"</string>
<string name="status_bar_settings_auto_rotation" msgid="8329080442278431708">"Auto-rotate screen"</string>
<string name="usb_device_permission_prompt" msgid="4414719028369181772">"Allow <xliff:g id="APPLICATION">%1$s</xliff:g> to access <xliff:g id="USB_DEVICE">%2$s</xliff:g>?"</string>
<string name="usb_device_permission_prompt_warn" msgid="2309129784984063656">"Allow <xliff:g id="APPLICATION">%1$s</xliff:g> to access <xliff:g id="USB_DEVICE">%2$s</xliff:g>?\nThis app has not been granted record permission but could capture audio through this USB device."</string>
@@ -130,8 +131,7 @@
<string name="biometric_dialog_face_icon_description_authenticated" msgid="2242167416140740920">"Face authenticated"</string>
<string name="biometric_dialog_face_icon_description_confirmed" msgid="7918067993953940778">"Confirmed"</string>
<string name="biometric_dialog_tap_confirm" msgid="9166350738859143358">"Tap Confirm to complete"</string>
- <!-- no translation found for biometric_dialog_tap_confirm_with_face (1597899891472340950) -->
- <skip />
+ <string name="biometric_dialog_tap_confirm_with_face" msgid="1597899891472340950">"Unlocked by your face. Press to continue."</string>
<string name="biometric_dialog_authenticated" msgid="7337147327545272484">"Authenticated"</string>
<string name="biometric_dialog_use_pin" msgid="8385294115283000709">"Use PIN"</string>
<string name="biometric_dialog_use_pattern" msgid="2315593393167211194">"Use pattern"</string>
@@ -459,8 +459,7 @@
<string name="wallet_secondary_label_device_locked" msgid="5175862019125370506">"Unlock to use"</string>
<string name="wallet_error_generic" msgid="257704570182963611">"There was a problem getting your cards. Please try again later."</string>
<string name="wallet_lockscreen_settings_label" msgid="3539105300870383570">"Lock screen settings"</string>
- <string name="qr_code_scanner_title" msgid="5660820608548306581">"QR code"</string>
- <string name="qr_code_scanner_description" msgid="7937603775306661863">"Tap to scan"</string>
+ <string name="qr_code_scanner_title" msgid="5290201053875420785">"Scan QR code"</string>
<string name="status_bar_work" msgid="5238641949837091056">"Work profile"</string>
<string name="status_bar_airplane" msgid="4848702508684541009">"Aeroplane mode"</string>
<string name="zen_alarm_warning" msgid="7844303238486849503">"You won\'t hear your next alarm <xliff:g id="WHEN">%1$s</xliff:g>"</string>
@@ -824,6 +823,7 @@
<string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"Pair new device"</string>
<string name="media_output_dialog_launch_app_text" msgid="1527413319632586259">"To cast this session, please open the app."</string>
<string name="media_output_dialog_unknown_launch_app_name" msgid="1084899329829371336">"Unknown app"</string>
+ <string name="media_output_dialog_button_stop_casting" msgid="6581379537930199189">"Stop casting"</string>
<string name="build_number_clip_data_label" msgid="3623176728412560914">"Build number"</string>
<string name="build_number_copy_toast" msgid="877720921605503046">"Build number copied to clipboard."</string>
<string name="basic_status" msgid="2315371112182658176">"Open conversation"</string>
@@ -910,15 +910,9 @@
<string name="add" msgid="81036585205287996">"Add"</string>
<string name="manage_users" msgid="1823875311934643849">"Manage users"</string>
<string name="drag_split_not_supported" msgid="4326847447699729722">"This notification does not support dragging to Split screen."</string>
- <!-- no translation found for dream_overlay_status_bar_wifi_off (4497069245055003582) -->
- <skip />
- <!-- no translation found for dream_overlay_status_bar_priority_mode (5428462123314728739) -->
- <skip />
- <!-- no translation found for dream_overlay_status_bar_alarm_set (566707328356590886) -->
- <skip />
- <!-- no translation found for dream_overlay_status_bar_assistant_guest_mode_enabled (3715897096012469615) -->
- <skip />
- <!-- no translation found for dream_overlay_status_bar_camera_mic_off (3199425257833773569) -->
- <skip />
+ <string name="dream_overlay_status_bar_wifi_off" msgid="4497069245055003582">"Wi‑Fi unavailable"</string>
+ <string name="dream_overlay_status_bar_priority_mode" msgid="5428462123314728739">"Priority mode"</string>
+ <string name="dream_overlay_status_bar_alarm_set" msgid="566707328356590886">"Alarm set"</string>
+ <string name="dream_overlay_status_bar_camera_mic_off" msgid="3199425257833773569">"Camera and mic are off"</string>
<string name="dream_overlay_status_bar_notification_indicator" msgid="8091389255691081711">"{count,plural, =1{# notification}other{# notifications}}"</string>
</resources>
diff --git a/packages/SystemUI/res/values-en-rCA/strings.xml b/packages/SystemUI/res/values-en-rCA/strings.xml
index 2e6514a..9a204eb 100644
--- a/packages/SystemUI/res/values-en-rCA/strings.xml
+++ b/packages/SystemUI/res/values-en-rCA/strings.xml
@@ -29,7 +29,8 @@
<string name="battery_saver_confirmation_title" msgid="1234998463717398453">"Turn on Battery Saver?"</string>
<string name="battery_saver_confirmation_title_generic" msgid="2299231884234959849">"About Battery Saver"</string>
<string name="battery_saver_confirmation_ok" msgid="5042136476802816494">"Turn on"</string>
- <string name="battery_saver_start_action" msgid="4553256017945469937">"Turn on Battery Saver"</string>
+ <string name="battery_saver_start_action" msgid="8353766979886287140">"Turn on"</string>
+ <string name="battery_saver_dismiss_action" msgid="7199342621040014738">"No thanks"</string>
<string name="status_bar_settings_auto_rotation" msgid="8329080442278431708">"Auto-rotate screen"</string>
<string name="usb_device_permission_prompt" msgid="4414719028369181772">"Allow <xliff:g id="APPLICATION">%1$s</xliff:g> to access <xliff:g id="USB_DEVICE">%2$s</xliff:g>?"</string>
<string name="usb_device_permission_prompt_warn" msgid="2309129784984063656">"Allow <xliff:g id="APPLICATION">%1$s</xliff:g> to access <xliff:g id="USB_DEVICE">%2$s</xliff:g>?\nThis app has not been granted record permission but could capture audio through this USB device."</string>
@@ -130,8 +131,7 @@
<string name="biometric_dialog_face_icon_description_authenticated" msgid="2242167416140740920">"Face authenticated"</string>
<string name="biometric_dialog_face_icon_description_confirmed" msgid="7918067993953940778">"Confirmed"</string>
<string name="biometric_dialog_tap_confirm" msgid="9166350738859143358">"Tap Confirm to complete"</string>
- <!-- no translation found for biometric_dialog_tap_confirm_with_face (1597899891472340950) -->
- <skip />
+ <string name="biometric_dialog_tap_confirm_with_face" msgid="1597899891472340950">"Unlocked by your face. Press to continue."</string>
<string name="biometric_dialog_authenticated" msgid="7337147327545272484">"Authenticated"</string>
<string name="biometric_dialog_use_pin" msgid="8385294115283000709">"Use PIN"</string>
<string name="biometric_dialog_use_pattern" msgid="2315593393167211194">"Use pattern"</string>
@@ -459,8 +459,7 @@
<string name="wallet_secondary_label_device_locked" msgid="5175862019125370506">"Unlock to use"</string>
<string name="wallet_error_generic" msgid="257704570182963611">"There was a problem getting your cards. Please try again later."</string>
<string name="wallet_lockscreen_settings_label" msgid="3539105300870383570">"Lock screen settings"</string>
- <string name="qr_code_scanner_title" msgid="5660820608548306581">"QR code"</string>
- <string name="qr_code_scanner_description" msgid="7937603775306661863">"Tap to scan"</string>
+ <string name="qr_code_scanner_title" msgid="5290201053875420785">"Scan QR code"</string>
<string name="status_bar_work" msgid="5238641949837091056">"Work profile"</string>
<string name="status_bar_airplane" msgid="4848702508684541009">"Airplane mode"</string>
<string name="zen_alarm_warning" msgid="7844303238486849503">"You won\'t hear your next alarm <xliff:g id="WHEN">%1$s</xliff:g>"</string>
@@ -824,6 +823,7 @@
<string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"Pair new device"</string>
<string name="media_output_dialog_launch_app_text" msgid="1527413319632586259">"To cast this session, please open the app."</string>
<string name="media_output_dialog_unknown_launch_app_name" msgid="1084899329829371336">"Unknown app"</string>
+ <string name="media_output_dialog_button_stop_casting" msgid="6581379537930199189">"Stop casting"</string>
<string name="build_number_clip_data_label" msgid="3623176728412560914">"Build number"</string>
<string name="build_number_copy_toast" msgid="877720921605503046">"Build number copied to clipboard."</string>
<string name="basic_status" msgid="2315371112182658176">"Open conversation"</string>
@@ -910,15 +910,9 @@
<string name="add" msgid="81036585205287996">"Add"</string>
<string name="manage_users" msgid="1823875311934643849">"Manage users"</string>
<string name="drag_split_not_supported" msgid="4326847447699729722">"This notification does not support dragging to Split screen."</string>
- <!-- no translation found for dream_overlay_status_bar_wifi_off (4497069245055003582) -->
- <skip />
- <!-- no translation found for dream_overlay_status_bar_priority_mode (5428462123314728739) -->
- <skip />
- <!-- no translation found for dream_overlay_status_bar_alarm_set (566707328356590886) -->
- <skip />
- <!-- no translation found for dream_overlay_status_bar_assistant_guest_mode_enabled (3715897096012469615) -->
- <skip />
- <!-- no translation found for dream_overlay_status_bar_camera_mic_off (3199425257833773569) -->
- <skip />
+ <string name="dream_overlay_status_bar_wifi_off" msgid="4497069245055003582">"Wi‑Fi unavailable"</string>
+ <string name="dream_overlay_status_bar_priority_mode" msgid="5428462123314728739">"Priority mode"</string>
+ <string name="dream_overlay_status_bar_alarm_set" msgid="566707328356590886">"Alarm set"</string>
+ <string name="dream_overlay_status_bar_camera_mic_off" msgid="3199425257833773569">"Camera and mic are off"</string>
<string name="dream_overlay_status_bar_notification_indicator" msgid="8091389255691081711">"{count,plural, =1{# notification}other{# notifications}}"</string>
</resources>
diff --git a/packages/SystemUI/res/values-en-rGB/strings.xml b/packages/SystemUI/res/values-en-rGB/strings.xml
index fcbe0a6..5544a95 100644
--- a/packages/SystemUI/res/values-en-rGB/strings.xml
+++ b/packages/SystemUI/res/values-en-rGB/strings.xml
@@ -29,7 +29,8 @@
<string name="battery_saver_confirmation_title" msgid="1234998463717398453">"Turn on Battery Saver?"</string>
<string name="battery_saver_confirmation_title_generic" msgid="2299231884234959849">"About Battery Saver"</string>
<string name="battery_saver_confirmation_ok" msgid="5042136476802816494">"Turn on"</string>
- <string name="battery_saver_start_action" msgid="4553256017945469937">"Turn on Battery Saver"</string>
+ <string name="battery_saver_start_action" msgid="8353766979886287140">"Turn on"</string>
+ <string name="battery_saver_dismiss_action" msgid="7199342621040014738">"No thanks"</string>
<string name="status_bar_settings_auto_rotation" msgid="8329080442278431708">"Auto-rotate screen"</string>
<string name="usb_device_permission_prompt" msgid="4414719028369181772">"Allow <xliff:g id="APPLICATION">%1$s</xliff:g> to access <xliff:g id="USB_DEVICE">%2$s</xliff:g>?"</string>
<string name="usb_device_permission_prompt_warn" msgid="2309129784984063656">"Allow <xliff:g id="APPLICATION">%1$s</xliff:g> to access <xliff:g id="USB_DEVICE">%2$s</xliff:g>?\nThis app has not been granted record permission but could capture audio through this USB device."</string>
@@ -130,8 +131,7 @@
<string name="biometric_dialog_face_icon_description_authenticated" msgid="2242167416140740920">"Face authenticated"</string>
<string name="biometric_dialog_face_icon_description_confirmed" msgid="7918067993953940778">"Confirmed"</string>
<string name="biometric_dialog_tap_confirm" msgid="9166350738859143358">"Tap Confirm to complete"</string>
- <!-- no translation found for biometric_dialog_tap_confirm_with_face (1597899891472340950) -->
- <skip />
+ <string name="biometric_dialog_tap_confirm_with_face" msgid="1597899891472340950">"Unlocked by your face. Press to continue."</string>
<string name="biometric_dialog_authenticated" msgid="7337147327545272484">"Authenticated"</string>
<string name="biometric_dialog_use_pin" msgid="8385294115283000709">"Use PIN"</string>
<string name="biometric_dialog_use_pattern" msgid="2315593393167211194">"Use pattern"</string>
@@ -459,8 +459,7 @@
<string name="wallet_secondary_label_device_locked" msgid="5175862019125370506">"Unlock to use"</string>
<string name="wallet_error_generic" msgid="257704570182963611">"There was a problem getting your cards. Please try again later."</string>
<string name="wallet_lockscreen_settings_label" msgid="3539105300870383570">"Lock screen settings"</string>
- <string name="qr_code_scanner_title" msgid="5660820608548306581">"QR code"</string>
- <string name="qr_code_scanner_description" msgid="7937603775306661863">"Tap to scan"</string>
+ <string name="qr_code_scanner_title" msgid="5290201053875420785">"Scan QR code"</string>
<string name="status_bar_work" msgid="5238641949837091056">"Work profile"</string>
<string name="status_bar_airplane" msgid="4848702508684541009">"Aeroplane mode"</string>
<string name="zen_alarm_warning" msgid="7844303238486849503">"You won\'t hear your next alarm <xliff:g id="WHEN">%1$s</xliff:g>"</string>
@@ -824,6 +823,7 @@
<string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"Pair new device"</string>
<string name="media_output_dialog_launch_app_text" msgid="1527413319632586259">"To cast this session, please open the app."</string>
<string name="media_output_dialog_unknown_launch_app_name" msgid="1084899329829371336">"Unknown app"</string>
+ <string name="media_output_dialog_button_stop_casting" msgid="6581379537930199189">"Stop casting"</string>
<string name="build_number_clip_data_label" msgid="3623176728412560914">"Build number"</string>
<string name="build_number_copy_toast" msgid="877720921605503046">"Build number copied to clipboard."</string>
<string name="basic_status" msgid="2315371112182658176">"Open conversation"</string>
@@ -910,15 +910,9 @@
<string name="add" msgid="81036585205287996">"Add"</string>
<string name="manage_users" msgid="1823875311934643849">"Manage users"</string>
<string name="drag_split_not_supported" msgid="4326847447699729722">"This notification does not support dragging to Split screen."</string>
- <!-- no translation found for dream_overlay_status_bar_wifi_off (4497069245055003582) -->
- <skip />
- <!-- no translation found for dream_overlay_status_bar_priority_mode (5428462123314728739) -->
- <skip />
- <!-- no translation found for dream_overlay_status_bar_alarm_set (566707328356590886) -->
- <skip />
- <!-- no translation found for dream_overlay_status_bar_assistant_guest_mode_enabled (3715897096012469615) -->
- <skip />
- <!-- no translation found for dream_overlay_status_bar_camera_mic_off (3199425257833773569) -->
- <skip />
+ <string name="dream_overlay_status_bar_wifi_off" msgid="4497069245055003582">"Wi‑Fi unavailable"</string>
+ <string name="dream_overlay_status_bar_priority_mode" msgid="5428462123314728739">"Priority mode"</string>
+ <string name="dream_overlay_status_bar_alarm_set" msgid="566707328356590886">"Alarm set"</string>
+ <string name="dream_overlay_status_bar_camera_mic_off" msgid="3199425257833773569">"Camera and mic are off"</string>
<string name="dream_overlay_status_bar_notification_indicator" msgid="8091389255691081711">"{count,plural, =1{# notification}other{# notifications}}"</string>
</resources>
diff --git a/packages/SystemUI/res/values-en-rIN/strings.xml b/packages/SystemUI/res/values-en-rIN/strings.xml
index fcbe0a6..5544a95 100644
--- a/packages/SystemUI/res/values-en-rIN/strings.xml
+++ b/packages/SystemUI/res/values-en-rIN/strings.xml
@@ -29,7 +29,8 @@
<string name="battery_saver_confirmation_title" msgid="1234998463717398453">"Turn on Battery Saver?"</string>
<string name="battery_saver_confirmation_title_generic" msgid="2299231884234959849">"About Battery Saver"</string>
<string name="battery_saver_confirmation_ok" msgid="5042136476802816494">"Turn on"</string>
- <string name="battery_saver_start_action" msgid="4553256017945469937">"Turn on Battery Saver"</string>
+ <string name="battery_saver_start_action" msgid="8353766979886287140">"Turn on"</string>
+ <string name="battery_saver_dismiss_action" msgid="7199342621040014738">"No thanks"</string>
<string name="status_bar_settings_auto_rotation" msgid="8329080442278431708">"Auto-rotate screen"</string>
<string name="usb_device_permission_prompt" msgid="4414719028369181772">"Allow <xliff:g id="APPLICATION">%1$s</xliff:g> to access <xliff:g id="USB_DEVICE">%2$s</xliff:g>?"</string>
<string name="usb_device_permission_prompt_warn" msgid="2309129784984063656">"Allow <xliff:g id="APPLICATION">%1$s</xliff:g> to access <xliff:g id="USB_DEVICE">%2$s</xliff:g>?\nThis app has not been granted record permission but could capture audio through this USB device."</string>
@@ -130,8 +131,7 @@
<string name="biometric_dialog_face_icon_description_authenticated" msgid="2242167416140740920">"Face authenticated"</string>
<string name="biometric_dialog_face_icon_description_confirmed" msgid="7918067993953940778">"Confirmed"</string>
<string name="biometric_dialog_tap_confirm" msgid="9166350738859143358">"Tap Confirm to complete"</string>
- <!-- no translation found for biometric_dialog_tap_confirm_with_face (1597899891472340950) -->
- <skip />
+ <string name="biometric_dialog_tap_confirm_with_face" msgid="1597899891472340950">"Unlocked by your face. Press to continue."</string>
<string name="biometric_dialog_authenticated" msgid="7337147327545272484">"Authenticated"</string>
<string name="biometric_dialog_use_pin" msgid="8385294115283000709">"Use PIN"</string>
<string name="biometric_dialog_use_pattern" msgid="2315593393167211194">"Use pattern"</string>
@@ -459,8 +459,7 @@
<string name="wallet_secondary_label_device_locked" msgid="5175862019125370506">"Unlock to use"</string>
<string name="wallet_error_generic" msgid="257704570182963611">"There was a problem getting your cards. Please try again later."</string>
<string name="wallet_lockscreen_settings_label" msgid="3539105300870383570">"Lock screen settings"</string>
- <string name="qr_code_scanner_title" msgid="5660820608548306581">"QR code"</string>
- <string name="qr_code_scanner_description" msgid="7937603775306661863">"Tap to scan"</string>
+ <string name="qr_code_scanner_title" msgid="5290201053875420785">"Scan QR code"</string>
<string name="status_bar_work" msgid="5238641949837091056">"Work profile"</string>
<string name="status_bar_airplane" msgid="4848702508684541009">"Aeroplane mode"</string>
<string name="zen_alarm_warning" msgid="7844303238486849503">"You won\'t hear your next alarm <xliff:g id="WHEN">%1$s</xliff:g>"</string>
@@ -824,6 +823,7 @@
<string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"Pair new device"</string>
<string name="media_output_dialog_launch_app_text" msgid="1527413319632586259">"To cast this session, please open the app."</string>
<string name="media_output_dialog_unknown_launch_app_name" msgid="1084899329829371336">"Unknown app"</string>
+ <string name="media_output_dialog_button_stop_casting" msgid="6581379537930199189">"Stop casting"</string>
<string name="build_number_clip_data_label" msgid="3623176728412560914">"Build number"</string>
<string name="build_number_copy_toast" msgid="877720921605503046">"Build number copied to clipboard."</string>
<string name="basic_status" msgid="2315371112182658176">"Open conversation"</string>
@@ -910,15 +910,9 @@
<string name="add" msgid="81036585205287996">"Add"</string>
<string name="manage_users" msgid="1823875311934643849">"Manage users"</string>
<string name="drag_split_not_supported" msgid="4326847447699729722">"This notification does not support dragging to Split screen."</string>
- <!-- no translation found for dream_overlay_status_bar_wifi_off (4497069245055003582) -->
- <skip />
- <!-- no translation found for dream_overlay_status_bar_priority_mode (5428462123314728739) -->
- <skip />
- <!-- no translation found for dream_overlay_status_bar_alarm_set (566707328356590886) -->
- <skip />
- <!-- no translation found for dream_overlay_status_bar_assistant_guest_mode_enabled (3715897096012469615) -->
- <skip />
- <!-- no translation found for dream_overlay_status_bar_camera_mic_off (3199425257833773569) -->
- <skip />
+ <string name="dream_overlay_status_bar_wifi_off" msgid="4497069245055003582">"Wi‑Fi unavailable"</string>
+ <string name="dream_overlay_status_bar_priority_mode" msgid="5428462123314728739">"Priority mode"</string>
+ <string name="dream_overlay_status_bar_alarm_set" msgid="566707328356590886">"Alarm set"</string>
+ <string name="dream_overlay_status_bar_camera_mic_off" msgid="3199425257833773569">"Camera and mic are off"</string>
<string name="dream_overlay_status_bar_notification_indicator" msgid="8091389255691081711">"{count,plural, =1{# notification}other{# notifications}}"</string>
</resources>
diff --git a/packages/SystemUI/res/values-en-rXC/strings.xml b/packages/SystemUI/res/values-en-rXC/strings.xml
index f05e75b..052f175 100644
--- a/packages/SystemUI/res/values-en-rXC/strings.xml
+++ b/packages/SystemUI/res/values-en-rXC/strings.xml
@@ -29,7 +29,8 @@
<string name="battery_saver_confirmation_title" msgid="1234998463717398453">"Turn on Battery Saver?"</string>
<string name="battery_saver_confirmation_title_generic" msgid="2299231884234959849">"About Battery Saver"</string>
<string name="battery_saver_confirmation_ok" msgid="5042136476802816494">"Turn on"</string>
- <string name="battery_saver_start_action" msgid="4553256017945469937">"Turn on Battery Saver"</string>
+ <string name="battery_saver_start_action" msgid="8353766979886287140">"Turn on"</string>
+ <string name="battery_saver_dismiss_action" msgid="7199342621040014738">"No thanks"</string>
<string name="status_bar_settings_auto_rotation" msgid="8329080442278431708">"Auto-rotate screen"</string>
<string name="usb_device_permission_prompt" msgid="4414719028369181772">"Allow <xliff:g id="APPLICATION">%1$s</xliff:g> to access <xliff:g id="USB_DEVICE">%2$s</xliff:g>?"</string>
<string name="usb_device_permission_prompt_warn" msgid="2309129784984063656">"Allow <xliff:g id="APPLICATION">%1$s</xliff:g> to access <xliff:g id="USB_DEVICE">%2$s</xliff:g>?\nThis app has not been granted record permission but could capture audio through this USB device."</string>
@@ -130,8 +131,7 @@
<string name="biometric_dialog_face_icon_description_authenticated" msgid="2242167416140740920">"Face authenticated"</string>
<string name="biometric_dialog_face_icon_description_confirmed" msgid="7918067993953940778">"Confirmed"</string>
<string name="biometric_dialog_tap_confirm" msgid="9166350738859143358">"Tap Confirm to complete"</string>
- <!-- no translation found for biometric_dialog_tap_confirm_with_face (1597899891472340950) -->
- <skip />
+ <string name="biometric_dialog_tap_confirm_with_face" msgid="1597899891472340950">"Unlocked by your face. Press to continue."</string>
<string name="biometric_dialog_authenticated" msgid="7337147327545272484">"Authenticated"</string>
<string name="biometric_dialog_use_pin" msgid="8385294115283000709">"Use PIN"</string>
<string name="biometric_dialog_use_pattern" msgid="2315593393167211194">"Use pattern"</string>
@@ -459,8 +459,7 @@
<string name="wallet_secondary_label_device_locked" msgid="5175862019125370506">"Unlock to use"</string>
<string name="wallet_error_generic" msgid="257704570182963611">"There was a problem getting your cards, please try again later"</string>
<string name="wallet_lockscreen_settings_label" msgid="3539105300870383570">"Lock screen settings"</string>
- <string name="qr_code_scanner_title" msgid="5660820608548306581">"QR code"</string>
- <string name="qr_code_scanner_description" msgid="7937603775306661863">"Tap to scan"</string>
+ <string name="qr_code_scanner_title" msgid="5290201053875420785">"Scan QR code"</string>
<string name="status_bar_work" msgid="5238641949837091056">"Work profile"</string>
<string name="status_bar_airplane" msgid="4848702508684541009">"Airplane mode"</string>
<string name="zen_alarm_warning" msgid="7844303238486849503">"You won\'t hear your next alarm <xliff:g id="WHEN">%1$s</xliff:g>"</string>
@@ -824,6 +823,7 @@
<string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"Pair new device"</string>
<string name="media_output_dialog_launch_app_text" msgid="1527413319632586259">"To cast this session, please open the app."</string>
<string name="media_output_dialog_unknown_launch_app_name" msgid="1084899329829371336">"Unknown app"</string>
+ <string name="media_output_dialog_button_stop_casting" msgid="6581379537930199189">"Stop casting"</string>
<string name="build_number_clip_data_label" msgid="3623176728412560914">"Build number"</string>
<string name="build_number_copy_toast" msgid="877720921605503046">"Build number copied to clipboard."</string>
<string name="basic_status" msgid="2315371112182658176">"Open conversation"</string>
@@ -913,7 +913,6 @@
<string name="dream_overlay_status_bar_wifi_off" msgid="4497069245055003582">"Wi‑Fi unavailable"</string>
<string name="dream_overlay_status_bar_priority_mode" msgid="5428462123314728739">"Priority mode"</string>
<string name="dream_overlay_status_bar_alarm_set" msgid="566707328356590886">"Alarm set"</string>
- <string name="dream_overlay_status_bar_assistant_guest_mode_enabled" msgid="3715897096012469615">"Assistant guest mode enabled"</string>
<string name="dream_overlay_status_bar_camera_mic_off" msgid="3199425257833773569">"Camera and mic are off"</string>
<string name="dream_overlay_status_bar_notification_indicator" msgid="8091389255691081711">"{count,plural, =1{# notification}other{# notifications}}"</string>
</resources>
diff --git a/packages/SystemUI/res/values-es-rUS/strings.xml b/packages/SystemUI/res/values-es-rUS/strings.xml
index 4363ce9..57996ee 100644
--- a/packages/SystemUI/res/values-es-rUS/strings.xml
+++ b/packages/SystemUI/res/values-es-rUS/strings.xml
@@ -20,19 +20,17 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_label" msgid="4811759950673118541">"IU del sistema"</string>
- <!-- no translation found for battery_low_title (5319680173344341779) -->
- <skip />
- <!-- no translation found for battery_low_description (3282977755476423966) -->
- <skip />
- <!-- no translation found for battery_low_intro (5148725009653088790) -->
- <skip />
+ <string name="battery_low_title" msgid="5319680173344341779">"¿Quieres activar el Ahorro de batería?"</string>
+ <string name="battery_low_description" msgid="3282977755476423966">"Tienes <xliff:g id="PERCENTAGE">%s</xliff:g> de batería restante. El Ahorro de batería activa el Tema oscuro, restringe la actividad en segundo plano y retrasa las notificaciones."</string>
+ <string name="battery_low_intro" msgid="5148725009653088790">"El Ahorro de batería activa el Tema oscuro, restringe la actividad en segundo plano y retrasa las notificaciones."</string>
<string name="battery_low_percent_format" msgid="4276661262843170964">"Queda un <xliff:g id="PERCENTAGE">%s</xliff:g> de batería."</string>
<string name="invalid_charger_title" msgid="938685362320735167">"No se puede cargar mediante USB"</string>
<string name="invalid_charger_text" msgid="2339310107232691577">"Usa el cargador que se incluyó con el dispositivo"</string>
<string name="battery_saver_confirmation_title" msgid="1234998463717398453">"¿Deseas activar Ahorro de batería?"</string>
<string name="battery_saver_confirmation_title_generic" msgid="2299231884234959849">"Acerca del Ahorro de batería"</string>
<string name="battery_saver_confirmation_ok" msgid="5042136476802816494">"Activar"</string>
- <string name="battery_saver_start_action" msgid="4553256017945469937">"Activar el Ahorro de batería"</string>
+ <string name="battery_saver_start_action" msgid="8353766979886287140">"Activar"</string>
+ <string name="battery_saver_dismiss_action" msgid="7199342621040014738">"No, gracias"</string>
<string name="status_bar_settings_auto_rotation" msgid="8329080442278431708">"Girar la pantalla automáticamente"</string>
<string name="usb_device_permission_prompt" msgid="4414719028369181772">"¿Deseas permitir que <xliff:g id="APPLICATION">%1$s</xliff:g> acceda a <xliff:g id="USB_DEVICE">%2$s</xliff:g>?"</string>
<string name="usb_device_permission_prompt_warn" msgid="2309129784984063656">"¿Quieres permitir que <xliff:g id="APPLICATION">%1$s</xliff:g> acceda a <xliff:g id="USB_DEVICE">%2$s</xliff:g>?\nLa app no tiene permiso para grabar, pero podría capturar audio mediante este dispositivo USB."</string>
@@ -133,8 +131,7 @@
<string name="biometric_dialog_face_icon_description_authenticated" msgid="2242167416140740920">"Se autenticó el rostro"</string>
<string name="biometric_dialog_face_icon_description_confirmed" msgid="7918067993953940778">"Confirmado"</string>
<string name="biometric_dialog_tap_confirm" msgid="9166350738859143358">"Presiona Confirmar para completar"</string>
- <!-- no translation found for biometric_dialog_tap_confirm_with_face (1597899891472340950) -->
- <skip />
+ <string name="biometric_dialog_tap_confirm_with_face" msgid="1597899891472340950">"Disp. desbloqueado con rostro. Presiona para continuar."</string>
<string name="biometric_dialog_authenticated" msgid="7337147327545272484">"Autenticado"</string>
<string name="biometric_dialog_use_pin" msgid="8385294115283000709">"Usar PIN"</string>
<string name="biometric_dialog_use_pattern" msgid="2315593393167211194">"Usar patrón"</string>
@@ -462,8 +459,8 @@
<string name="wallet_secondary_label_device_locked" msgid="5175862019125370506">"Desbloquear para usar"</string>
<string name="wallet_error_generic" msgid="257704570182963611">"Ocurrió un problema al obtener las tarjetas; vuelve a intentarlo más tarde"</string>
<string name="wallet_lockscreen_settings_label" msgid="3539105300870383570">"Configuración de pantalla de bloqueo"</string>
- <string name="qr_code_scanner_title" msgid="5660820608548306581">"Código QR"</string>
- <string name="qr_code_scanner_description" msgid="7937603775306661863">"Presiona para escanear"</string>
+ <!-- no translation found for qr_code_scanner_title (5290201053875420785) -->
+ <skip />
<string name="status_bar_work" msgid="5238641949837091056">"Perfil de trabajo"</string>
<string name="status_bar_airplane" msgid="4848702508684541009">"Modo de avión"</string>
<string name="zen_alarm_warning" msgid="7844303238486849503">"No oirás la próxima alarma a la(s) <xliff:g id="WHEN">%1$s</xliff:g>"</string>
@@ -827,6 +824,7 @@
<string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"Vincular dispositivo nuevo"</string>
<string name="media_output_dialog_launch_app_text" msgid="1527413319632586259">"Para transmitir esta sesión, abre la app"</string>
<string name="media_output_dialog_unknown_launch_app_name" msgid="1084899329829371336">"App desconocida"</string>
+ <string name="media_output_dialog_button_stop_casting" msgid="6581379537930199189">"Detener transmisión"</string>
<string name="build_number_clip_data_label" msgid="3623176728412560914">"Número de compilación"</string>
<string name="build_number_copy_toast" msgid="877720921605503046">"Se copió el número de compilación en el portapapeles."</string>
<string name="basic_status" msgid="2315371112182658176">"Conversación abierta"</string>
@@ -916,7 +914,6 @@
<string name="dream_overlay_status_bar_wifi_off" msgid="4497069245055003582">"La red Wi-Fi no está disponible"</string>
<string name="dream_overlay_status_bar_priority_mode" msgid="5428462123314728739">"Modo prioridad"</string>
<string name="dream_overlay_status_bar_alarm_set" msgid="566707328356590886">"Se estableció la alarma"</string>
- <string name="dream_overlay_status_bar_assistant_guest_mode_enabled" msgid="3715897096012469615">"Se habilitó el Modo de Invitado de Asistente"</string>
<string name="dream_overlay_status_bar_camera_mic_off" msgid="3199425257833773569">"La cámara y el micrófono están apagados"</string>
<string name="dream_overlay_status_bar_notification_indicator" msgid="8091389255691081711">"{count,plural, =1{# notificación}other{# notificaciones}}"</string>
</resources>
diff --git a/packages/SystemUI/res/values-es/strings.xml b/packages/SystemUI/res/values-es/strings.xml
index 0e7be44..f4a8cf7 100644
--- a/packages/SystemUI/res/values-es/strings.xml
+++ b/packages/SystemUI/res/values-es/strings.xml
@@ -20,19 +20,17 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_label" msgid="4811759950673118541">"UI del sistema"</string>
- <!-- no translation found for battery_low_title (5319680173344341779) -->
- <skip />
- <!-- no translation found for battery_low_description (3282977755476423966) -->
- <skip />
- <!-- no translation found for battery_low_intro (5148725009653088790) -->
- <skip />
+ <string name="battery_low_title" msgid="5319680173344341779">"¿Activar Ahorro de batería?"</string>
+ <string name="battery_low_description" msgid="3282977755476423966">"Te queda un <xliff:g id="PERCENTAGE">%s</xliff:g> de batería. Ahorro de batería activa el tema oscuro, restringe la actividad en segundo plano y retrasa las notificaciones."</string>
+ <string name="battery_low_intro" msgid="5148725009653088790">"Ahorro de batería activa el tema oscuro, restringe la actividad en segundo plano y retrasa las notificaciones."</string>
<string name="battery_low_percent_format" msgid="4276661262843170964">"Queda un <xliff:g id="PERCENTAGE">%s</xliff:g> de batería"</string>
<string name="invalid_charger_title" msgid="938685362320735167">"No se puede cargar por USB"</string>
<string name="invalid_charger_text" msgid="2339310107232691577">"Utiliza el cargador original incluido con el dispositivo"</string>
<string name="battery_saver_confirmation_title" msgid="1234998463717398453">"¿Activar Ahorro de batería?"</string>
<string name="battery_saver_confirmation_title_generic" msgid="2299231884234959849">"Información de Ahorro de batería"</string>
<string name="battery_saver_confirmation_ok" msgid="5042136476802816494">"Activar"</string>
- <string name="battery_saver_start_action" msgid="4553256017945469937">"Activar Ahorro de batería"</string>
+ <string name="battery_saver_start_action" msgid="8353766979886287140">"Activar"</string>
+ <string name="battery_saver_dismiss_action" msgid="7199342621040014738">"No, gracias"</string>
<string name="status_bar_settings_auto_rotation" msgid="8329080442278431708">"Girar pantalla automáticamente"</string>
<string name="usb_device_permission_prompt" msgid="4414719028369181772">"¿Permitir que <xliff:g id="APPLICATION">%1$s</xliff:g> acceda a <xliff:g id="USB_DEVICE">%2$s</xliff:g>?"</string>
<string name="usb_device_permission_prompt_warn" msgid="2309129784984063656">"¿Quieres que <xliff:g id="APPLICATION">%1$s</xliff:g> pueda acceder a <xliff:g id="USB_DEVICE">%2$s</xliff:g>?\nEsta aplicación no tiene permisos para grabar, pero podría captar audio a través de este dispositivo USB."</string>
@@ -133,8 +131,7 @@
<string name="biometric_dialog_face_icon_description_authenticated" msgid="2242167416140740920">"Cara autenticada"</string>
<string name="biometric_dialog_face_icon_description_confirmed" msgid="7918067993953940778">"Confirmada"</string>
<string name="biometric_dialog_tap_confirm" msgid="9166350738859143358">"Toca Confirmar para completar la acción"</string>
- <!-- no translation found for biometric_dialog_tap_confirm_with_face (1597899891472340950) -->
- <skip />
+ <string name="biometric_dialog_tap_confirm_with_face" msgid="1597899891472340950">"Desbloqueada con la cara. Pulsa para continuar."</string>
<string name="biometric_dialog_authenticated" msgid="7337147327545272484">"Se ha autenticado"</string>
<string name="biometric_dialog_use_pin" msgid="8385294115283000709">"Usar PIN"</string>
<string name="biometric_dialog_use_pattern" msgid="2315593393167211194">"Usar patrón"</string>
@@ -462,8 +459,8 @@
<string name="wallet_secondary_label_device_locked" msgid="5175862019125370506">"Desbloquear para usar"</string>
<string name="wallet_error_generic" msgid="257704570182963611">"Se ha producido un problema al obtener tus tarjetas. Inténtalo de nuevo más tarde."</string>
<string name="wallet_lockscreen_settings_label" msgid="3539105300870383570">"Ajustes de pantalla de bloqueo"</string>
- <string name="qr_code_scanner_title" msgid="5660820608548306581">"Código QR"</string>
- <string name="qr_code_scanner_description" msgid="7937603775306661863">"Toca para escanear"</string>
+ <!-- no translation found for qr_code_scanner_title (5290201053875420785) -->
+ <skip />
<string name="status_bar_work" msgid="5238641949837091056">"Perfil de trabajo"</string>
<string name="status_bar_airplane" msgid="4848702508684541009">"Modo avión"</string>
<string name="zen_alarm_warning" msgid="7844303238486849503">"No oirás la próxima alarma (<xliff:g id="WHEN">%1$s</xliff:g>)"</string>
@@ -827,6 +824,7 @@
<string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"Emparejar nuevo dispositivo"</string>
<string name="media_output_dialog_launch_app_text" msgid="1527413319632586259">"Para enviar esta sesión, abre la aplicación."</string>
<string name="media_output_dialog_unknown_launch_app_name" msgid="1084899329829371336">"Aplicación desconocida"</string>
+ <string name="media_output_dialog_button_stop_casting" msgid="6581379537930199189">"Dejar de enviar contenido"</string>
<string name="build_number_clip_data_label" msgid="3623176728412560914">"Número de compilación"</string>
<string name="build_number_copy_toast" msgid="877720921605503046">"Número de compilación copiado en el portapapeles."</string>
<string name="basic_status" msgid="2315371112182658176">"Conversación abierta"</string>
@@ -916,8 +914,6 @@
<string name="dream_overlay_status_bar_wifi_off" msgid="4497069245055003582">"Wi‑Fi no disponible"</string>
<string name="dream_overlay_status_bar_priority_mode" msgid="5428462123314728739">"Modo prioritario"</string>
<string name="dream_overlay_status_bar_alarm_set" msgid="566707328356590886">"Alarma añadida"</string>
- <string name="dream_overlay_status_bar_assistant_guest_mode_enabled" msgid="3715897096012469615">"Modo invitado del asistente habilitado"</string>
<string name="dream_overlay_status_bar_camera_mic_off" msgid="3199425257833773569">"La cámara y el micrófono están desactivados"</string>
- <!-- no translation found for dream_overlay_status_bar_notification_indicator (8091389255691081711) -->
- <skip />
+ <string name="dream_overlay_status_bar_notification_indicator" msgid="8091389255691081711">"{count,plural, =1{# notificación}other{# notificaciones}}"</string>
</resources>
diff --git a/packages/SystemUI/res/values-et/strings.xml b/packages/SystemUI/res/values-et/strings.xml
index 0c9d46e..b6d266c 100644
--- a/packages/SystemUI/res/values-et/strings.xml
+++ b/packages/SystemUI/res/values-et/strings.xml
@@ -20,19 +20,17 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_label" msgid="4811759950673118541">"Süsteemi UI"</string>
- <!-- no translation found for battery_low_title (5319680173344341779) -->
- <skip />
- <!-- no translation found for battery_low_description (3282977755476423966) -->
- <skip />
- <!-- no translation found for battery_low_intro (5148725009653088790) -->
- <skip />
+ <string name="battery_low_title" msgid="5319680173344341779">"Kas lülitada akusäästja sisse?"</string>
+ <string name="battery_low_description" msgid="3282977755476423966">"Teil on jäänud <xliff:g id="PERCENTAGE">%s</xliff:g> akutoidet. Akusäästja lülitab sisse tumeda teema, piirab taustategevusi ja viivitab märguannete saatmisega."</string>
+ <string name="battery_low_intro" msgid="5148725009653088790">"Akusäästja lülitab sisse tumeda teema, piirab taustategevusi ja viivitab märguannete saatmisega."</string>
<string name="battery_low_percent_format" msgid="4276661262843170964">"Jäänud on <xliff:g id="PERCENTAGE">%s</xliff:g>"</string>
<string name="invalid_charger_title" msgid="938685362320735167">"Ei saa USB kaudu laadida"</string>
<string name="invalid_charger_text" msgid="2339310107232691577">"Kasutage seadmega kaasas olnud laadijat"</string>
<string name="battery_saver_confirmation_title" msgid="1234998463717398453">"Kas lülitada akusäästja sisse?"</string>
<string name="battery_saver_confirmation_title_generic" msgid="2299231884234959849">"Teave akusäästja kohta"</string>
<string name="battery_saver_confirmation_ok" msgid="5042136476802816494">"Lülita sisse"</string>
- <string name="battery_saver_start_action" msgid="4553256017945469937">"Akusäästja sisselülitamine"</string>
+ <string name="battery_saver_start_action" msgid="8353766979886287140">"Lülita sisse"</string>
+ <string name="battery_saver_dismiss_action" msgid="7199342621040014738">"Tänan, ei"</string>
<string name="status_bar_settings_auto_rotation" msgid="8329080442278431708">"Kuva automaatne pööramine"</string>
<string name="usb_device_permission_prompt" msgid="4414719028369181772">"Kas lubada rakendusele <xliff:g id="APPLICATION">%1$s</xliff:g> juurdepääs seadmele <xliff:g id="USB_DEVICE">%2$s</xliff:g>?"</string>
<string name="usb_device_permission_prompt_warn" msgid="2309129784984063656">"Kas lubada rakendusel <xliff:g id="APPLICATION">%1$s</xliff:g> seadmele <xliff:g id="USB_DEVICE">%2$s</xliff:g> juurde pääseda?\nSellele rakendusele pole antud salvestamise luba, kuid see saab heli jäädvustada selle USB-seadme kaudu."</string>
@@ -133,8 +131,7 @@
<string name="biometric_dialog_face_icon_description_authenticated" msgid="2242167416140740920">"Nägu on autenditud"</string>
<string name="biometric_dialog_face_icon_description_confirmed" msgid="7918067993953940778">"Kinnitatud"</string>
<string name="biometric_dialog_tap_confirm" msgid="9166350738859143358">"Lõpuleviimiseks puudutage nuppu Kinnita"</string>
- <!-- no translation found for biometric_dialog_tap_confirm_with_face (1597899891472340950) -->
- <skip />
+ <string name="biometric_dialog_tap_confirm_with_face" msgid="1597899891472340950">"Avati teie näoga. Vajutage jätkamiseks."</string>
<string name="biometric_dialog_authenticated" msgid="7337147327545272484">"Autenditud"</string>
<string name="biometric_dialog_use_pin" msgid="8385294115283000709">"Kasuta PIN-koodi"</string>
<string name="biometric_dialog_use_pattern" msgid="2315593393167211194">"Kasuta mustrit"</string>
@@ -462,8 +459,8 @@
<string name="wallet_secondary_label_device_locked" msgid="5175862019125370506">"Avage kasutamiseks"</string>
<string name="wallet_error_generic" msgid="257704570182963611">"Teie kaartide hankimisel ilmnes probleem, proovige hiljem uuesti"</string>
<string name="wallet_lockscreen_settings_label" msgid="3539105300870383570">"Lukustuskuva seaded"</string>
- <string name="qr_code_scanner_title" msgid="5660820608548306581">"QR-kood"</string>
- <string name="qr_code_scanner_description" msgid="7937603775306661863">"Skannimiseks puudutamine"</string>
+ <!-- no translation found for qr_code_scanner_title (5290201053875420785) -->
+ <skip />
<string name="status_bar_work" msgid="5238641949837091056">"Tööprofiil"</string>
<string name="status_bar_airplane" msgid="4848702508684541009">"Lennukirežiim"</string>
<string name="zen_alarm_warning" msgid="7844303238486849503">"Te ei kuule järgmist äratust kell <xliff:g id="WHEN">%1$s</xliff:g>"</string>
@@ -827,6 +824,7 @@
<string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"Uue seadme sidumine"</string>
<string name="media_output_dialog_launch_app_text" msgid="1527413319632586259">"Selle seansi ülekandmiseks avage rakendus."</string>
<string name="media_output_dialog_unknown_launch_app_name" msgid="1084899329829371336">"Tundmatu rakendus"</string>
+ <string name="media_output_dialog_button_stop_casting" msgid="6581379537930199189">"Lõpeta ülekanne"</string>
<string name="build_number_clip_data_label" msgid="3623176728412560914">"Järgunumber"</string>
<string name="build_number_copy_toast" msgid="877720921605503046">"Järgunumber kopeeriti lõikelauale."</string>
<string name="basic_status" msgid="2315371112182658176">"Avage vestlus"</string>
@@ -916,8 +914,6 @@
<string name="dream_overlay_status_bar_wifi_off" msgid="4497069245055003582">"WiFi pole saadaval"</string>
<string name="dream_overlay_status_bar_priority_mode" msgid="5428462123314728739">"Režiim Prioriteetne"</string>
<string name="dream_overlay_status_bar_alarm_set" msgid="566707328356590886">"Alarm on määratud"</string>
- <string name="dream_overlay_status_bar_assistant_guest_mode_enabled" msgid="3715897096012469615">"Assistendi külalisrežiim on lubatud"</string>
<string name="dream_overlay_status_bar_camera_mic_off" msgid="3199425257833773569">"Kaamera ja mikrofon on välja lülitatud"</string>
- <!-- no translation found for dream_overlay_status_bar_notification_indicator (8091389255691081711) -->
- <skip />
+ <string name="dream_overlay_status_bar_notification_indicator" msgid="8091389255691081711">"{count,plural, =1{# märguanne}other{# märguannet}}"</string>
</resources>
diff --git a/packages/SystemUI/res/values-eu/strings.xml b/packages/SystemUI/res/values-eu/strings.xml
index 90d24e5..768c202 100644
--- a/packages/SystemUI/res/values-eu/strings.xml
+++ b/packages/SystemUI/res/values-eu/strings.xml
@@ -20,19 +20,17 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_label" msgid="4811759950673118541">"Sistemaren interfazea"</string>
- <!-- no translation found for battery_low_title (5319680173344341779) -->
- <skip />
- <!-- no translation found for battery_low_description (3282977755476423966) -->
- <skip />
- <!-- no translation found for battery_low_intro (5148725009653088790) -->
- <skip />
+ <string name="battery_low_title" msgid="5319680173344341779">"Bateria-aurrezlea aktibatu nahi duzu?"</string>
+ <string name="battery_low_description" msgid="3282977755476423966">"Bateriaren <xliff:g id="PERCENTAGE">%s</xliff:g> gelditzen zaizu. Bateria-aurrezleak gai iluna aktibatzen du, atzeko planoko jarduerak murrizten, eta jakinarazpenak atzeratzen."</string>
+ <string name="battery_low_intro" msgid="5148725009653088790">"Bateria-aurrezleak gai iluna aktibatzen du, atzeko planoko jarduerak murrizten, eta jakinarazpenak atzeratzen."</string>
<string name="battery_low_percent_format" msgid="4276661262843170964">"<xliff:g id="PERCENTAGE">%s</xliff:g> gelditzen da"</string>
<string name="invalid_charger_title" msgid="938685362320735167">"Ezin da USB bidez kargatu"</string>
<string name="invalid_charger_text" msgid="2339310107232691577">"Erabili gailuaren kargagailua"</string>
<string name="battery_saver_confirmation_title" msgid="1234998463717398453">"Bateria-aurrezlea aktibatu nahi duzu?"</string>
<string name="battery_saver_confirmation_title_generic" msgid="2299231884234959849">"Bateria-aurrezleari buruz"</string>
<string name="battery_saver_confirmation_ok" msgid="5042136476802816494">"Aktibatu"</string>
- <string name="battery_saver_start_action" msgid="4553256017945469937">"Aktibatu bateria-aurrezlea"</string>
+ <string name="battery_saver_start_action" msgid="8353766979886287140">"Aktibatu"</string>
+ <string name="battery_saver_dismiss_action" msgid="7199342621040014738">"Ez, eskerrik asko"</string>
<string name="status_bar_settings_auto_rotation" msgid="8329080442278431708">"Biratu pantaila automatikoki"</string>
<string name="usb_device_permission_prompt" msgid="4414719028369181772">"<xliff:g id="USB_DEVICE">%2$s</xliff:g> atzitzeko baimena eman nahi diozu <xliff:g id="APPLICATION">%1$s</xliff:g> aplikazioari?"</string>
<string name="usb_device_permission_prompt_warn" msgid="2309129784984063656">"<xliff:g id="USB_DEVICE">%2$s</xliff:g> erabiltzeko baimena eman nahi diozu <xliff:g id="APPLICATION">%1$s</xliff:g> aplikazioari?\nAplikazioak ez du grabatzeko baimenik, baina baliteke USB bidezko gailu horren bidez audioa grabatzea."</string>
@@ -133,8 +131,7 @@
<string name="biometric_dialog_face_icon_description_authenticated" msgid="2242167416140740920">"Autentifikatu da aurpegia"</string>
<string name="biometric_dialog_face_icon_description_confirmed" msgid="7918067993953940778">"Berretsita"</string>
<string name="biometric_dialog_tap_confirm" msgid="9166350738859143358">"Amaitzeko, sakatu \"Berretsi\""</string>
- <!-- no translation found for biometric_dialog_tap_confirm_with_face (1597899891472340950) -->
- <skip />
+ <string name="biometric_dialog_tap_confirm_with_face" msgid="1597899891472340950">"Aurpegiaren bidez desblokeatu da. Sakatu aurrera egiteko."</string>
<string name="biometric_dialog_authenticated" msgid="7337147327545272484">"Autentifikatuta"</string>
<string name="biometric_dialog_use_pin" msgid="8385294115283000709">"Erabili PINa"</string>
<string name="biometric_dialog_use_pattern" msgid="2315593393167211194">"Erabili eredua"</string>
@@ -197,7 +194,7 @@
<string name="accessibility_casting_turned_off" msgid="1387906158563374962">"Pantaila igortzeari utzi zaio."</string>
<string name="accessibility_brightness" msgid="5391187016177823721">"Bistaratu distira"</string>
<string name="data_usage_disabled_dialog_mobile_title" msgid="2286843518689837719">"Datu-konexioa pausatu egin da"</string>
- <string name="data_usage_disabled_dialog_title" msgid="9131615296036724838">"Datuen erabilera pausatu da"</string>
+ <string name="data_usage_disabled_dialog_title" msgid="9131615296036724838">"Datu-erabilera pausatu da"</string>
<string name="data_usage_disabled_dialog" msgid="7933201635215099780">"Iritsi zara ezarri zenuen datu-mugara. Datu-konexioa erabiltzeari utzi diozu.\n\nDatu-konexioa erabiltzeari berrekiten badiozu, baliteke zerbait ordaindu behar izatea datuak erabiltzeagatik."</string>
<string name="data_usage_disabled_dialog_enable" msgid="2796648546086408937">"Jarraitu erabiltzen"</string>
<string name="accessibility_location_active" msgid="2845747916764660369">"Aplikazioen kokapen-eskaerak aktibo daude"</string>
@@ -261,7 +258,7 @@
<string name="quick_settings_flashlight_label" msgid="4904634272006284185">"Linterna"</string>
<string name="quick_settings_flashlight_camera_in_use" msgid="4820591564526512571">"Kamera abian da"</string>
<string name="quick_settings_cellular_detail_title" msgid="792977203299358893">"Datu-konexioa"</string>
- <string name="quick_settings_cellular_detail_data_usage" msgid="6105969068871138427">"Datuen erabilera"</string>
+ <string name="quick_settings_cellular_detail_data_usage" msgid="6105969068871138427">"Datu-erabilera"</string>
<string name="quick_settings_cellular_detail_remaining_data" msgid="1136599216568805644">"Geratzen diren datuak"</string>
<string name="quick_settings_cellular_detail_over_limit" msgid="4561921367680636235">"Mugaren gainetik"</string>
<string name="quick_settings_cellular_detail_data_used" msgid="6798849610647988987">"<xliff:g id="DATA_USED">%s</xliff:g> erabilita"</string>
@@ -462,8 +459,8 @@
<string name="wallet_secondary_label_device_locked" msgid="5175862019125370506">"Desblokeatu erabiltzeko"</string>
<string name="wallet_error_generic" msgid="257704570182963611">"Arazo bat izan da txartelak eskuratzean. Saiatu berriro geroago."</string>
<string name="wallet_lockscreen_settings_label" msgid="3539105300870383570">"Pantaila blokeatuaren ezarpenak"</string>
- <string name="qr_code_scanner_title" msgid="5660820608548306581">"QR kodea"</string>
- <string name="qr_code_scanner_description" msgid="7937603775306661863">"Sakatu eskaneatzeko"</string>
+ <!-- no translation found for qr_code_scanner_title (5290201053875420785) -->
+ <skip />
<string name="status_bar_work" msgid="5238641949837091056">"Work profila"</string>
<string name="status_bar_airplane" msgid="4848702508684541009">"Hegaldi modua"</string>
<string name="zen_alarm_warning" msgid="7844303238486849503">"Ez duzu entzungo hurrengo alarma (<xliff:g id="WHEN">%1$s</xliff:g>)"</string>
@@ -702,7 +699,7 @@
<string name="qs_dnd_prompt_app" msgid="4027984447935396820">"Ez molestatzeko modua aktibatu du aplikazio batek (<xliff:g id="ID_1">%s</xliff:g>)."</string>
<string name="qs_dnd_prompt_auto_rule_app" msgid="1841469944118486580">"Ez molestatzeko modua aktibatu du arau automatiko edo aplikazio batek."</string>
<string name="running_foreground_services_title" msgid="5137313173431186685">"Aplikazioak abian dira atzeko planoan"</string>
- <string name="running_foreground_services_msg" msgid="3009459259222695385">"Sakatu bateria eta datuen erabilerari buruzko xehetasunak ikusteko"</string>
+ <string name="running_foreground_services_msg" msgid="3009459259222695385">"Sakatu bateria eta datu-erabilerari buruzko xehetasunak ikusteko"</string>
<string name="mobile_data_disable_title" msgid="5366476131671617790">"Datu-konexioa desaktibatu nahi duzu?"</string>
<string name="mobile_data_disable_message" msgid="8604966027899770415">"<xliff:g id="CARRIER">%s</xliff:g> erabilita ezingo dituzu erabili datuak edo Internet. Wifi-sare baten bidez soilik konektatu ahal izango zara Internetera."</string>
<string name="mobile_data_disable_message_default_carrier" msgid="6496033312431658238">"Zure operadorea"</string>
@@ -827,6 +824,7 @@
<string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"Parekatu beste gailu batekin"</string>
<string name="media_output_dialog_launch_app_text" msgid="1527413319632586259">"Saioa ireki nahi baduzu, ireki aplikazioa."</string>
<string name="media_output_dialog_unknown_launch_app_name" msgid="1084899329829371336">"Aplikazio ezezaguna"</string>
+ <string name="media_output_dialog_button_stop_casting" msgid="6581379537930199189">"Utzi igortzeari"</string>
<string name="build_number_clip_data_label" msgid="3623176728412560914">"Konpilazio-zenbakia"</string>
<string name="build_number_copy_toast" msgid="877720921605503046">"Kopiatu da konpilazio-zenbakia arbelean."</string>
<string name="basic_status" msgid="2315371112182658176">"Elkarrizketa irekia"</string>
@@ -916,8 +914,6 @@
<string name="dream_overlay_status_bar_wifi_off" msgid="4497069245055003582">"Wifi-konexioa ez dago erabilgarri"</string>
<string name="dream_overlay_status_bar_priority_mode" msgid="5428462123314728739">"Lehentasun modua"</string>
<string name="dream_overlay_status_bar_alarm_set" msgid="566707328356590886">"Alarma ezarrita dago"</string>
- <string name="dream_overlay_status_bar_assistant_guest_mode_enabled" msgid="3715897096012469615">"Laguntzailea zerbitzuaren gonbidatu modua gaituta dago"</string>
<string name="dream_overlay_status_bar_camera_mic_off" msgid="3199425257833773569">"Kamera eta mikrofonoa desaktibatuta daude"</string>
- <!-- no translation found for dream_overlay_status_bar_notification_indicator (8091389255691081711) -->
- <skip />
+ <string name="dream_overlay_status_bar_notification_indicator" msgid="8091389255691081711">"{count,plural, =1{# jakinarazpen}other{# jakinarazpen}}"</string>
</resources>
diff --git a/packages/SystemUI/res/values-fa/strings.xml b/packages/SystemUI/res/values-fa/strings.xml
index 99e214b..3e76c46 100644
--- a/packages/SystemUI/res/values-fa/strings.xml
+++ b/packages/SystemUI/res/values-fa/strings.xml
@@ -20,19 +20,17 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_label" msgid="4811759950673118541">"میانای کاربر سیستم"</string>
- <!-- no translation found for battery_low_title (5319680173344341779) -->
- <skip />
- <!-- no translation found for battery_low_description (3282977755476423966) -->
- <skip />
- <!-- no translation found for battery_low_intro (5148725009653088790) -->
- <skip />
+ <string name="battery_low_title" msgid="5319680173344341779">"«بهینهسازی باتری» روشن شود؟"</string>
+ <string name="battery_low_description" msgid="3282977755476423966">"<xliff:g id="PERCENTAGE">%s</xliff:g> از باتریتان باقی مانده است. «بهینهسازی باتری» زمینه تیره را روشن میکند، فعالیتهای پسزمینه را محدود میکند، و اعلانها را بهتأخیر میاندازد."</string>
+ <string name="battery_low_intro" msgid="5148725009653088790">"«بهینهسازی باتری» زمینه تیره را روشن میکند، فعالیتهای پسزمینه را محدود میکند، و اعلانها را بهتأخیر میاندازد."</string>
<string name="battery_low_percent_format" msgid="4276661262843170964">"<xliff:g id="PERCENTAGE">%s</xliff:g> باقی مانده است"</string>
<string name="invalid_charger_title" msgid="938685362320735167">"ازطریق USB شارژ نمیشود"</string>
<string name="invalid_charger_text" msgid="2339310107232691577">"از شارژر ارائهشده با دستگاه استفاده کنید"</string>
<string name="battery_saver_confirmation_title" msgid="1234998463717398453">"«بهینهسازی باتری» روشن شود؟"</string>
<string name="battery_saver_confirmation_title_generic" msgid="2299231884234959849">"درباره «بهینهسازی باتری»"</string>
<string name="battery_saver_confirmation_ok" msgid="5042136476802816494">"روشن کردن"</string>
- <string name="battery_saver_start_action" msgid="4553256017945469937">"«بهینهسازی باتری» را روشن کنید"</string>
+ <string name="battery_saver_start_action" msgid="8353766979886287140">"روشن کردن"</string>
+ <string name="battery_saver_dismiss_action" msgid="7199342621040014738">"نه متشکرم"</string>
<string name="status_bar_settings_auto_rotation" msgid="8329080442278431708">"چرخش خودکار صفحه"</string>
<string name="usb_device_permission_prompt" msgid="4414719028369181772">"به <xliff:g id="APPLICATION">%1$s</xliff:g> برای دسترسی به <xliff:g id="USB_DEVICE">%2$s</xliff:g> اجازه داده شود؟"</string>
<string name="usb_device_permission_prompt_warn" msgid="2309129784984063656">"به <xliff:g id="APPLICATION">%1$s</xliff:g> اجازه میدهید به <xliff:g id="USB_DEVICE">%2$s</xliff:g>دسترسی داشته باشد؟\nمجوز ضبط به این برنامه داده نشده است اما میتواند صدا را ازطریق این دستگاه USB ضبط کند."</string>
@@ -133,8 +131,7 @@
<string name="biometric_dialog_face_icon_description_authenticated" msgid="2242167416140740920">"چهره اصالتسنجی شد"</string>
<string name="biometric_dialog_face_icon_description_confirmed" msgid="7918067993953940778">"تأیید شد"</string>
<string name="biometric_dialog_tap_confirm" msgid="9166350738859143358">"برای تکمیل، روی تأیید ضربه بزنید"</string>
- <!-- no translation found for biometric_dialog_tap_confirm_with_face (1597899891472340950) -->
- <skip />
+ <string name="biometric_dialog_tap_confirm_with_face" msgid="1597899891472340950">"قفل با چهرهتان باز شد. برای ادامه دادن، فشار دهید."</string>
<string name="biometric_dialog_authenticated" msgid="7337147327545272484">"راستیآزماییشده"</string>
<string name="biometric_dialog_use_pin" msgid="8385294115283000709">"استفاده از پین"</string>
<string name="biometric_dialog_use_pattern" msgid="2315593393167211194">"استفاده از الگو"</string>
@@ -273,7 +270,7 @@
<string name="quick_settings_night_secondary_label_until_sunrise" msgid="4063448287758262485">"تا طلوع"</string>
<string name="quick_settings_night_secondary_label_on_at" msgid="3584738542293528235">"ساعت <xliff:g id="TIME">%s</xliff:g> روشن میشود"</string>
<string name="quick_settings_secondary_label_until" msgid="1883981263191927372">"تا <xliff:g id="TIME">%s</xliff:g>"</string>
- <string name="quick_settings_ui_mode_night_label" msgid="1398928270610780470">"طرح زمینه تیره"</string>
+ <string name="quick_settings_ui_mode_night_label" msgid="1398928270610780470">"زمینه تیره"</string>
<string name="quick_settings_dark_mode_secondary_label_battery_saver" msgid="4990712734503013251">"بهینهسازی باتری"</string>
<string name="quick_settings_dark_mode_secondary_label_on_at_sunset" msgid="6017379738102015710">"غروب روشن میشود"</string>
<string name="quick_settings_dark_mode_secondary_label_until_sunrise" msgid="4404885070316716472">"تا طلوع آفتاب"</string>
@@ -462,8 +459,8 @@
<string name="wallet_secondary_label_device_locked" msgid="5175862019125370506">"برای استفاده، قفل را باز کنید"</string>
<string name="wallet_error_generic" msgid="257704570182963611">"هنگام دریافت کارتها مشکلی پیش آمد، لطفاً بعداً دوباره امتحان کنید"</string>
<string name="wallet_lockscreen_settings_label" msgid="3539105300870383570">"تنظیمات صفحه قفل"</string>
- <string name="qr_code_scanner_title" msgid="5660820608548306581">"رمزینه پاسخسریع"</string>
- <string name="qr_code_scanner_description" msgid="7937603775306661863">"برای اسکن کردن، ضربه بزنید"</string>
+ <!-- no translation found for qr_code_scanner_title (5290201053875420785) -->
+ <skip />
<string name="status_bar_work" msgid="5238641949837091056">"نمایه کاری"</string>
<string name="status_bar_airplane" msgid="4848702508684541009">"حالت هواپیما"</string>
<string name="zen_alarm_warning" msgid="7844303238486849503">"در ساعت <xliff:g id="WHEN">%1$s</xliff:g>، دیگر صدای زنگ ساعت را نمیشنوید"</string>
@@ -827,6 +824,7 @@
<string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"مرتبط کردن دستگاه جدید"</string>
<string name="media_output_dialog_launch_app_text" msgid="1527413319632586259">"برای ارسال محتوای این جلسه، لطفاً برنامه را باز کنید."</string>
<string name="media_output_dialog_unknown_launch_app_name" msgid="1084899329829371336">"برنامه ناشناس"</string>
+ <string name="media_output_dialog_button_stop_casting" msgid="6581379537930199189">"توقف ارسال محتوا"</string>
<string name="build_number_clip_data_label" msgid="3623176728412560914">"شماره ساخت"</string>
<string name="build_number_copy_toast" msgid="877720921605503046">"شماره ساخت در بریدهدان کپی شد."</string>
<string name="basic_status" msgid="2315371112182658176">"باز کردن مکالمه"</string>
@@ -916,8 +914,6 @@
<string name="dream_overlay_status_bar_wifi_off" msgid="4497069245055003582">"Wi‑Fi دردسترس نیست"</string>
<string name="dream_overlay_status_bar_priority_mode" msgid="5428462123314728739">"حالت اولویت"</string>
<string name="dream_overlay_status_bar_alarm_set" msgid="566707328356590886">"زنگ ساعت تنظیم شد"</string>
- <string name="dream_overlay_status_bar_assistant_guest_mode_enabled" msgid="3715897096012469615">"«حالت مهمان» «دستیار» فعال شد"</string>
<string name="dream_overlay_status_bar_camera_mic_off" msgid="3199425257833773569">"دوربین و میکروفون خاموش هستند"</string>
- <!-- no translation found for dream_overlay_status_bar_notification_indicator (8091389255691081711) -->
- <skip />
+ <string name="dream_overlay_status_bar_notification_indicator" msgid="8091389255691081711">"{count,plural, =1{# اعلان}one{# اعلان}other{# اعلان}}"</string>
</resources>
diff --git a/packages/SystemUI/res/values-fi/strings.xml b/packages/SystemUI/res/values-fi/strings.xml
index 5aca1ce..3257d8b 100644
--- a/packages/SystemUI/res/values-fi/strings.xml
+++ b/packages/SystemUI/res/values-fi/strings.xml
@@ -20,19 +20,17 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_label" msgid="4811759950673118541">"Käyttöliitt."</string>
- <!-- no translation found for battery_low_title (5319680173344341779) -->
- <skip />
- <!-- no translation found for battery_low_description (3282977755476423966) -->
- <skip />
- <!-- no translation found for battery_low_intro (5148725009653088790) -->
- <skip />
+ <string name="battery_low_title" msgid="5319680173344341779">"Laitetaanko virransäästö päälle?"</string>
+ <string name="battery_low_description" msgid="3282977755476423966">"Akkua jäljellä <xliff:g id="PERCENTAGE">%s</xliff:g>. Virransäästö laittaa tumman teeman päälle, rajoittaa taustatoimintoja ja viivästyttää ilmoituksia."</string>
+ <string name="battery_low_intro" msgid="5148725009653088790">"Virransäästö laittaa tumman teeman päälle, rajoittaa taustatoimintoja ja viivästyttää ilmoituksia."</string>
<string name="battery_low_percent_format" msgid="4276661262843170964">"<xliff:g id="PERCENTAGE">%s</xliff:g> jäljellä"</string>
<string name="invalid_charger_title" msgid="938685362320735167">"Lataaminen USB:llä ei onnistu"</string>
<string name="invalid_charger_text" msgid="2339310107232691577">"Käytä laitteesi mukana tullutta laturia"</string>
<string name="battery_saver_confirmation_title" msgid="1234998463717398453">"Otetaanko virransäästö käyttöön?"</string>
<string name="battery_saver_confirmation_title_generic" msgid="2299231884234959849">"Tietoa virransäästöstä"</string>
<string name="battery_saver_confirmation_ok" msgid="5042136476802816494">"Ota käyttöön"</string>
- <string name="battery_saver_start_action" msgid="4553256017945469937">"Ota virransäästö käyttöön"</string>
+ <string name="battery_saver_start_action" msgid="8353766979886287140">"Laita päälle"</string>
+ <string name="battery_saver_dismiss_action" msgid="7199342621040014738">"Ei kiitos"</string>
<string name="status_bar_settings_auto_rotation" msgid="8329080442278431708">"Näytön automaattinen kääntö"</string>
<string name="usb_device_permission_prompt" msgid="4414719028369181772">"Saako <xliff:g id="APPLICATION">%1$s</xliff:g> käyttöoikeuden (<xliff:g id="USB_DEVICE">%2$s</xliff:g>)?"</string>
<string name="usb_device_permission_prompt_warn" msgid="2309129784984063656">"Saako <xliff:g id="APPLICATION">%1$s</xliff:g> tämän pääsyoikeuden: <xliff:g id="USB_DEVICE">%2$s</xliff:g>?\nSovellus ei ole saanut tallennuslupaa, mutta voi tallentaa ääntä tämän USB-laitteen avulla."</string>
@@ -133,8 +131,7 @@
<string name="biometric_dialog_face_icon_description_authenticated" msgid="2242167416140740920">"Kasvot tunnistettu"</string>
<string name="biometric_dialog_face_icon_description_confirmed" msgid="7918067993953940778">"Vahvistettu"</string>
<string name="biometric_dialog_tap_confirm" msgid="9166350738859143358">"Valitse lopuksi Vahvista"</string>
- <!-- no translation found for biometric_dialog_tap_confirm_with_face (1597899891472340950) -->
- <skip />
+ <string name="biometric_dialog_tap_confirm_with_face" msgid="1597899891472340950">"Lukitus avattu kasvojen avulla. Jatka painamalla."</string>
<string name="biometric_dialog_authenticated" msgid="7337147327545272484">"Todennettu"</string>
<string name="biometric_dialog_use_pin" msgid="8385294115283000709">"Käytä PIN-koodia"</string>
<string name="biometric_dialog_use_pattern" msgid="2315593393167211194">"Käytä kuviota"</string>
@@ -462,8 +459,8 @@
<string name="wallet_secondary_label_device_locked" msgid="5175862019125370506">"Avaa lukitus ja käytä"</string>
<string name="wallet_error_generic" msgid="257704570182963611">"Korttien noutamisessa oli ongelma, yritä myöhemmin uudelleen"</string>
<string name="wallet_lockscreen_settings_label" msgid="3539105300870383570">"Lukitusnäytön asetukset"</string>
- <string name="qr_code_scanner_title" msgid="5660820608548306581">"QR-koodi"</string>
- <string name="qr_code_scanner_description" msgid="7937603775306661863">"Skannaa napauttamalla"</string>
+ <!-- no translation found for qr_code_scanner_title (5290201053875420785) -->
+ <skip />
<string name="status_bar_work" msgid="5238641949837091056">"Työprofiili"</string>
<string name="status_bar_airplane" msgid="4848702508684541009">"Lentokonetila"</string>
<string name="zen_alarm_warning" msgid="7844303238486849503">"Et kuule seuraavaa hälytystäsi (<xliff:g id="WHEN">%1$s</xliff:g>)."</string>
@@ -827,6 +824,7 @@
<string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"Muodosta uusi laitepari"</string>
<string name="media_output_dialog_launch_app_text" msgid="1527413319632586259">"Jos haluat striimata tämän käyttökerran, avaa sovellus."</string>
<string name="media_output_dialog_unknown_launch_app_name" msgid="1084899329829371336">"Tuntematon sovellus"</string>
+ <string name="media_output_dialog_button_stop_casting" msgid="6581379537930199189">"Lopeta striimaus"</string>
<string name="build_number_clip_data_label" msgid="3623176728412560914">"Koontiversion numero"</string>
<string name="build_number_copy_toast" msgid="877720921605503046">"Koontiversion numero kopioitu leikepöydälle"</string>
<string name="basic_status" msgid="2315371112182658176">"Avaa keskustelu"</string>
@@ -916,8 +914,6 @@
<string name="dream_overlay_status_bar_wifi_off" msgid="4497069245055003582">"Wi‑Fi ei ole saatavilla"</string>
<string name="dream_overlay_status_bar_priority_mode" msgid="5428462123314728739">"Tärkeät-tila"</string>
<string name="dream_overlay_status_bar_alarm_set" msgid="566707328356590886">"Hälytys asetettu"</string>
- <string name="dream_overlay_status_bar_assistant_guest_mode_enabled" msgid="3715897096012469615">"Assistantin vierastila käytössä"</string>
<string name="dream_overlay_status_bar_camera_mic_off" msgid="3199425257833773569">"Kamera ja mikrofoni ovat pois päältä"</string>
- <!-- no translation found for dream_overlay_status_bar_notification_indicator (8091389255691081711) -->
- <skip />
+ <string name="dream_overlay_status_bar_notification_indicator" msgid="8091389255691081711">"{count,plural, =1{# ilmoitus}other{# ilmoitusta}}"</string>
</resources>
diff --git a/packages/SystemUI/res/values-fr-rCA/strings.xml b/packages/SystemUI/res/values-fr-rCA/strings.xml
index 1a599b5..e91e55d 100644
--- a/packages/SystemUI/res/values-fr-rCA/strings.xml
+++ b/packages/SystemUI/res/values-fr-rCA/strings.xml
@@ -20,19 +20,17 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_label" msgid="4811759950673118541">"IU système"</string>
- <!-- no translation found for battery_low_title (5319680173344341779) -->
- <skip />
- <!-- no translation found for battery_low_description (3282977755476423966) -->
- <skip />
- <!-- no translation found for battery_low_intro (5148725009653088790) -->
- <skip />
+ <string name="battery_low_title" msgid="5319680173344341779">"Activer l\'économiseur de pile?"</string>
+ <string name="battery_low_description" msgid="3282977755476423966">"Il vous reste <xliff:g id="PERCENTAGE">%s</xliff:g> d\'autonomie. L\'économiseur de pile active le thème sombre, limite l\'activité en arrière-plan et retarde les notifications."</string>
+ <string name="battery_low_intro" msgid="5148725009653088790">"L\'économiseur de pile active le thème sombre, limite l\'activité en arrière-plan et retarde les notifications."</string>
<string name="battery_low_percent_format" msgid="4276661262843170964">"<xliff:g id="PERCENTAGE">%s</xliff:g> restants"</string>
<string name="invalid_charger_title" msgid="938685362320735167">"Impossible de charger l\'appareil par USB"</string>
<string name="invalid_charger_text" msgid="2339310107232691577">"Servez-vous du chargeur fourni avec votre appareil"</string>
<string name="battery_saver_confirmation_title" msgid="1234998463717398453">"Activer l\'économiseur de pile?"</string>
<string name="battery_saver_confirmation_title_generic" msgid="2299231884234959849">"À propos du mode Économiseur de pile"</string>
<string name="battery_saver_confirmation_ok" msgid="5042136476802816494">"Activer"</string>
- <string name="battery_saver_start_action" msgid="4553256017945469937">"Activer l\'économiseur de pile"</string>
+ <string name="battery_saver_start_action" msgid="8353766979886287140">"Activer"</string>
+ <string name="battery_saver_dismiss_action" msgid="7199342621040014738">"Non merci"</string>
<string name="status_bar_settings_auto_rotation" msgid="8329080442278431708">"Rotation auto de l\'écran"</string>
<string name="usb_device_permission_prompt" msgid="4414719028369181772">"Autoriser <xliff:g id="APPLICATION">%1$s</xliff:g> à accéder à <xliff:g id="USB_DEVICE">%2$s</xliff:g>?"</string>
<string name="usb_device_permission_prompt_warn" msgid="2309129784984063656">"Autorisé <xliff:g id="APPLICATION">%1$s</xliff:g> à accéder à <xliff:g id="USB_DEVICE">%2$s</xliff:g>?\nCette application n\'a pas été autorisée à effectuer des enregistrements, mais elle pourrait enregistrer du contenu audio par l\'intermédiaire de cet appareil USB."</string>
@@ -133,8 +131,7 @@
<string name="biometric_dialog_face_icon_description_authenticated" msgid="2242167416140740920">"Visage authentifié"</string>
<string name="biometric_dialog_face_icon_description_confirmed" msgid="7918067993953940778">"Confirmé"</string>
<string name="biometric_dialog_tap_confirm" msgid="9166350738859143358">"Touchez Confirmer pour terminer"</string>
- <!-- no translation found for biometric_dialog_tap_confirm_with_face (1597899891472340950) -->
- <skip />
+ <string name="biometric_dialog_tap_confirm_with_face" msgid="1597899891472340950">"Déverrouillé par votre visage. Appuyez pour continuer."</string>
<string name="biometric_dialog_authenticated" msgid="7337147327545272484">"Authentifié"</string>
<string name="biometric_dialog_use_pin" msgid="8385294115283000709">"Utiliser un NIP"</string>
<string name="biometric_dialog_use_pattern" msgid="2315593393167211194">"Utiliser un schéma"</string>
@@ -462,8 +459,8 @@
<string name="wallet_secondary_label_device_locked" msgid="5175862019125370506">"Déverrouiller pour utiliser"</string>
<string name="wallet_error_generic" msgid="257704570182963611">"Un problème est survenu lors de la récupération de vos cartes, veuillez réessayer plus tard"</string>
<string name="wallet_lockscreen_settings_label" msgid="3539105300870383570">"Paramètres de l\'écran de verrouillage"</string>
- <string name="qr_code_scanner_title" msgid="5660820608548306581">"Code QR"</string>
- <string name="qr_code_scanner_description" msgid="7937603775306661863">"Touchez pour numériser"</string>
+ <!-- no translation found for qr_code_scanner_title (5290201053875420785) -->
+ <skip />
<string name="status_bar_work" msgid="5238641949837091056">"Profil professionnel"</string>
<string name="status_bar_airplane" msgid="4848702508684541009">"Mode Avion"</string>
<string name="zen_alarm_warning" msgid="7844303238486849503">"Vous n\'entendrez pas votre prochaine alarme à <xliff:g id="WHEN">%1$s</xliff:g>"</string>
@@ -827,6 +824,7 @@
<string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"Associer un autre appareil"</string>
<string name="media_output_dialog_launch_app_text" msgid="1527413319632586259">"Pour diffuser cette session, veuillez ouvrir l\'application."</string>
<string name="media_output_dialog_unknown_launch_app_name" msgid="1084899329829371336">"Application inconnue"</string>
+ <string name="media_output_dialog_button_stop_casting" msgid="6581379537930199189">"Arrêter la diffusion"</string>
<string name="build_number_clip_data_label" msgid="3623176728412560914">"Numéro de version"</string>
<string name="build_number_copy_toast" msgid="877720921605503046">"Le numéro de version a été copié dans le presse-papiers."</string>
<string name="basic_status" msgid="2315371112182658176">"Ouvrir la conversation"</string>
@@ -916,8 +914,6 @@
<string name="dream_overlay_status_bar_wifi_off" msgid="4497069245055003582">"Wi-Fi non disponible"</string>
<string name="dream_overlay_status_bar_priority_mode" msgid="5428462123314728739">"Mode priorité"</string>
<string name="dream_overlay_status_bar_alarm_set" msgid="566707328356590886">"L\'alarme a été réglée"</string>
- <string name="dream_overlay_status_bar_assistant_guest_mode_enabled" msgid="3715897096012469615">"Mode Invité de l\'assistant activé"</string>
<string name="dream_overlay_status_bar_camera_mic_off" msgid="3199425257833773569">"L\'appareil photo et le micro sont désactivés"</string>
- <!-- no translation found for dream_overlay_status_bar_notification_indicator (8091389255691081711) -->
- <skip />
+ <string name="dream_overlay_status_bar_notification_indicator" msgid="8091389255691081711">"{count,plural, =1{# notification}one{# notification}other{# notifications}}"</string>
</resources>
diff --git a/packages/SystemUI/res/values-fr/strings.xml b/packages/SystemUI/res/values-fr/strings.xml
index 1465bdb..33194aa 100644
--- a/packages/SystemUI/res/values-fr/strings.xml
+++ b/packages/SystemUI/res/values-fr/strings.xml
@@ -20,19 +20,17 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_label" msgid="4811759950673118541">"Interface"</string>
- <!-- no translation found for battery_low_title (5319680173344341779) -->
- <skip />
- <!-- no translation found for battery_low_description (3282977755476423966) -->
- <skip />
- <!-- no translation found for battery_low_intro (5148725009653088790) -->
- <skip />
+ <string name="battery_low_title" msgid="5319680173344341779">"Activer l\'économiseur de batterie ?"</string>
+ <string name="battery_low_description" msgid="3282977755476423966">"Il vous reste <xliff:g id="PERCENTAGE">%s</xliff:g> de batterie. L\'économiseur de batterie active le thème sombre, limite les activités en arrière-plan et retarde les notifications."</string>
+ <string name="battery_low_intro" msgid="5148725009653088790">"L\'économiseur de batterie active le thème sombre, limite les activités en arrière-plan et retarde les notifications."</string>
<string name="battery_low_percent_format" msgid="4276661262843170964">"<xliff:g id="PERCENTAGE">%s</xliff:g> restants"</string>
<string name="invalid_charger_title" msgid="938685362320735167">"Impossible de recharger via USB"</string>
<string name="invalid_charger_text" msgid="2339310107232691577">"Utiliser le chargeur d\'origine fourni avec votre appareil"</string>
<string name="battery_saver_confirmation_title" msgid="1234998463717398453">"Activer l\'économiseur de batterie ?"</string>
<string name="battery_saver_confirmation_title_generic" msgid="2299231884234959849">"À propos de l\'économiseur de batterie"</string>
<string name="battery_saver_confirmation_ok" msgid="5042136476802816494">"Activer"</string>
- <string name="battery_saver_start_action" msgid="4553256017945469937">"Activer l\'économiseur de batterie"</string>
+ <string name="battery_saver_start_action" msgid="8353766979886287140">"Activer"</string>
+ <string name="battery_saver_dismiss_action" msgid="7199342621040014738">"Non, merci"</string>
<string name="status_bar_settings_auto_rotation" msgid="8329080442278431708">"Rotation automatique de l\'écran"</string>
<string name="usb_device_permission_prompt" msgid="4414719028369181772">"Autoriser <xliff:g id="APPLICATION">%1$s</xliff:g> à accéder à <xliff:g id="USB_DEVICE">%2$s</xliff:g> ?"</string>
<string name="usb_device_permission_prompt_warn" msgid="2309129784984063656">"Autoriser <xliff:g id="APPLICATION">%1$s</xliff:g> à accéder à <xliff:g id="USB_DEVICE">%2$s</xliff:g> ?\nCette application n\'a pas été autorisée à effectuer des enregistrements, mais elle pourrait enregistrer du contenu audio via ce périphérique USB."</string>
@@ -133,8 +131,7 @@
<string name="biometric_dialog_face_icon_description_authenticated" msgid="2242167416140740920">"Visage authentifié"</string>
<string name="biometric_dialog_face_icon_description_confirmed" msgid="7918067993953940778">"Confirmé"</string>
<string name="biometric_dialog_tap_confirm" msgid="9166350738859143358">"Appuyez sur \"Confirmer\" pour terminer"</string>
- <!-- no translation found for biometric_dialog_tap_confirm_with_face (1597899891472340950) -->
- <skip />
+ <string name="biometric_dialog_tap_confirm_with_face" msgid="1597899891472340950">"Déverrouillé par votre visage. Appuyez pour continuer."</string>
<string name="biometric_dialog_authenticated" msgid="7337147327545272484">"Authentifié"</string>
<string name="biometric_dialog_use_pin" msgid="8385294115283000709">"Utiliser un code PIN"</string>
<string name="biometric_dialog_use_pattern" msgid="2315593393167211194">"Utiliser un schéma"</string>
@@ -462,8 +459,8 @@
<string name="wallet_secondary_label_device_locked" msgid="5175862019125370506">"Déverrouiller pour utiliser"</string>
<string name="wallet_error_generic" msgid="257704570182963611">"Problème de récupération de vos cartes. Réessayez plus tard"</string>
<string name="wallet_lockscreen_settings_label" msgid="3539105300870383570">"Paramètres de l\'écran de verrouillage"</string>
- <string name="qr_code_scanner_title" msgid="5660820608548306581">"Code QR"</string>
- <string name="qr_code_scanner_description" msgid="7937603775306661863">"Appuyer pour scanner"</string>
+ <!-- no translation found for qr_code_scanner_title (5290201053875420785) -->
+ <skip />
<string name="status_bar_work" msgid="5238641949837091056">"Profil professionnel"</string>
<string name="status_bar_airplane" msgid="4848702508684541009">"Mode Avion"</string>
<string name="zen_alarm_warning" msgid="7844303238486849503">"Vous n\'entendrez pas votre prochaine alarme <xliff:g id="WHEN">%1$s</xliff:g>."</string>
@@ -827,6 +824,7 @@
<string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"Associer un nouvel appareil"</string>
<string name="media_output_dialog_launch_app_text" msgid="1527413319632586259">"Pour caster cette session, veuillez ouvrir l\'appli."</string>
<string name="media_output_dialog_unknown_launch_app_name" msgid="1084899329829371336">"Appli inconnue"</string>
+ <string name="media_output_dialog_button_stop_casting" msgid="6581379537930199189">"Arrêter la diffusion"</string>
<string name="build_number_clip_data_label" msgid="3623176728412560914">"Numéro de build"</string>
<string name="build_number_copy_toast" msgid="877720921605503046">"Numéro de build copié dans le presse-papiers."</string>
<string name="basic_status" msgid="2315371112182658176">"Conversation ouverte"</string>
@@ -916,8 +914,6 @@
<string name="dream_overlay_status_bar_wifi_off" msgid="4497069245055003582">"Wi‑Fi non disponible"</string>
<string name="dream_overlay_status_bar_priority_mode" msgid="5428462123314728739">"Mode Prioritaire"</string>
<string name="dream_overlay_status_bar_alarm_set" msgid="566707328356590886">"Alarme réglée"</string>
- <string name="dream_overlay_status_bar_assistant_guest_mode_enabled" msgid="3715897096012469615">"Mode Invité activé pour l\'Assistant"</string>
<string name="dream_overlay_status_bar_camera_mic_off" msgid="3199425257833773569">"Appareil photo et micro désactivés"</string>
- <!-- no translation found for dream_overlay_status_bar_notification_indicator (8091389255691081711) -->
- <skip />
+ <string name="dream_overlay_status_bar_notification_indicator" msgid="8091389255691081711">"{count,plural, =1{# notification}one{# notification}other{# notifications}}"</string>
</resources>
diff --git a/packages/SystemUI/res/values-gl/strings.xml b/packages/SystemUI/res/values-gl/strings.xml
index 5faa3df..52a55e7 100644
--- a/packages/SystemUI/res/values-gl/strings.xml
+++ b/packages/SystemUI/res/values-gl/strings.xml
@@ -20,19 +20,17 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_label" msgid="4811759950673118541">"IU do sistema"</string>
- <!-- no translation found for battery_low_title (5319680173344341779) -->
- <skip />
- <!-- no translation found for battery_low_description (3282977755476423966) -->
- <skip />
- <!-- no translation found for battery_low_intro (5148725009653088790) -->
- <skip />
+ <string name="battery_low_title" msgid="5319680173344341779">"Queres activar a función Aforro de batería?"</string>
+ <string name="battery_low_description" msgid="3282977755476423966">"Quédache un <xliff:g id="PERCENTAGE">%s</xliff:g> de batería. Coa función Aforro de batería, actívase o tema escuro, restrínxese a actividade en segundo plano e atrásanse as notificacións."</string>
+ <string name="battery_low_intro" msgid="5148725009653088790">"Coa función Aforro de batería, actívase o tema escuro, restrínxese a actividade en segundo plano e atrásanse as notificacións."</string>
<string name="battery_low_percent_format" msgid="4276661262843170964">"<xliff:g id="PERCENTAGE">%s</xliff:g> restante"</string>
<string name="invalid_charger_title" msgid="938685362320735167">"Non se puido realizar a carga por USB"</string>
<string name="invalid_charger_text" msgid="2339310107232691577">"Utiliza o cargador que incluía o dispositivo"</string>
<string name="battery_saver_confirmation_title" msgid="1234998463717398453">"Queres activar a función Aforro de batería?"</string>
<string name="battery_saver_confirmation_title_generic" msgid="2299231884234959849">"Acerca de Aforro de batería"</string>
<string name="battery_saver_confirmation_ok" msgid="5042136476802816494">"Activar"</string>
- <string name="battery_saver_start_action" msgid="4553256017945469937">"Activar a función Aforro de batería"</string>
+ <string name="battery_saver_start_action" msgid="8353766979886287140">"Activar"</string>
+ <string name="battery_saver_dismiss_action" msgid="7199342621040014738">"Non, grazas"</string>
<string name="status_bar_settings_auto_rotation" msgid="8329080442278431708">"Xirar pantalla automaticamente"</string>
<string name="usb_device_permission_prompt" msgid="4414719028369181772">"Queres permitir que <xliff:g id="APPLICATION">%1$s</xliff:g> acceda a <xliff:g id="USB_DEVICE">%2$s</xliff:g>?"</string>
<string name="usb_device_permission_prompt_warn" msgid="2309129784984063656">"Queres permitir que a aplicación <xliff:g id="APPLICATION">%1$s</xliff:g> acceda ao dispositivo (<xliff:g id="USB_DEVICE">%2$s</xliff:g>)?\nEsta aplicación non está autorizada para realizar gravacións, pero pode capturar audio a través deste dispositivo USB."</string>
@@ -133,8 +131,7 @@
<string name="biometric_dialog_face_icon_description_authenticated" msgid="2242167416140740920">"Autenticouse a cara"</string>
<string name="biometric_dialog_face_icon_description_confirmed" msgid="7918067993953940778">"Confirmada"</string>
<string name="biometric_dialog_tap_confirm" msgid="9166350738859143358">"Toca Confirmar para completar o proceso"</string>
- <!-- no translation found for biometric_dialog_tap_confirm_with_face (1597899891472340950) -->
- <skip />
+ <string name="biometric_dialog_tap_confirm_with_face" msgid="1597899891472340950">"Desbloqueouse coa túa cara. Preme para continuar."</string>
<string name="biometric_dialog_authenticated" msgid="7337147327545272484">"Autenticado"</string>
<string name="biometric_dialog_use_pin" msgid="8385294115283000709">"Usar PIN"</string>
<string name="biometric_dialog_use_pattern" msgid="2315593393167211194">"Usar padrón"</string>
@@ -462,8 +459,8 @@
<string name="wallet_secondary_label_device_locked" msgid="5175862019125370506">"Desbloquear para usar"</string>
<string name="wallet_error_generic" msgid="257704570182963611">"Produciuse un problema ao obter as tarxetas. Téntao de novo máis tarde"</string>
<string name="wallet_lockscreen_settings_label" msgid="3539105300870383570">"Configuración da pantalla de bloqueo"</string>
- <string name="qr_code_scanner_title" msgid="5660820608548306581">"Código QR"</string>
- <string name="qr_code_scanner_description" msgid="7937603775306661863">"Tocar para escanear"</string>
+ <!-- no translation found for qr_code_scanner_title (5290201053875420785) -->
+ <skip />
<string name="status_bar_work" msgid="5238641949837091056">"Perfil de traballo"</string>
<string name="status_bar_airplane" msgid="4848702508684541009">"Modo avión"</string>
<string name="zen_alarm_warning" msgid="7844303238486849503">"Non escoitarás a alarma seguinte <xliff:g id="WHEN">%1$s</xliff:g>"</string>
@@ -827,6 +824,7 @@
<string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"Vincular dispositivo novo"</string>
<string name="media_output_dialog_launch_app_text" msgid="1527413319632586259">"Para emitir esta sesión, abre a aplicación."</string>
<string name="media_output_dialog_unknown_launch_app_name" msgid="1084899329829371336">"Aplicación descoñecida"</string>
+ <string name="media_output_dialog_button_stop_casting" msgid="6581379537930199189">"Deter emisión"</string>
<string name="build_number_clip_data_label" msgid="3623176728412560914">"Número de compilación"</string>
<string name="build_number_copy_toast" msgid="877720921605503046">"Copiouse o número de compilación no portapapeis."</string>
<string name="basic_status" msgid="2315371112182658176">"Conversa aberta"</string>
@@ -916,8 +914,6 @@
<string name="dream_overlay_status_bar_wifi_off" msgid="4497069245055003582">"A wifi non está dispoñible"</string>
<string name="dream_overlay_status_bar_priority_mode" msgid="5428462123314728739">"Modo de prioridade"</string>
<string name="dream_overlay_status_bar_alarm_set" msgid="566707328356590886">"Alarma definida"</string>
- <string name="dream_overlay_status_bar_assistant_guest_mode_enabled" msgid="3715897096012469615">"O modo Convidados do Asistente está activado"</string>
<string name="dream_overlay_status_bar_camera_mic_off" msgid="3199425257833773569">"A cámara e o micrófono están desactivados"</string>
- <!-- no translation found for dream_overlay_status_bar_notification_indicator (8091389255691081711) -->
- <skip />
+ <string name="dream_overlay_status_bar_notification_indicator" msgid="8091389255691081711">"{count,plural, =1{# notificación}other{# notificacións}}"</string>
</resources>
diff --git a/packages/SystemUI/res/values-gu/strings.xml b/packages/SystemUI/res/values-gu/strings.xml
index 763d39d..497029e 100644
--- a/packages/SystemUI/res/values-gu/strings.xml
+++ b/packages/SystemUI/res/values-gu/strings.xml
@@ -20,19 +20,17 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_label" msgid="4811759950673118541">"સિસ્ટમ UI"</string>
- <!-- no translation found for battery_low_title (5319680173344341779) -->
- <skip />
- <!-- no translation found for battery_low_description (3282977755476423966) -->
- <skip />
- <!-- no translation found for battery_low_intro (5148725009653088790) -->
- <skip />
+ <string name="battery_low_title" msgid="5319680173344341779">"બૅટરી સેવર ચાલુ કરીએ?"</string>
+ <string name="battery_low_description" msgid="3282977755476423966">"તમારી પાસે <xliff:g id="PERCENTAGE">%s</xliff:g> બૅટરી બાકી છે. બૅટરી સેવર ઘેરી થીમની સુવિધા ચાલુ કરે છે, બૅકગ્રાઉન્ડ પ્રવૃત્તિ પ્રતિબંધિત કરે છે અને નોટિફિકેશન વિલંબે મોકલે છે."</string>
+ <string name="battery_low_intro" msgid="5148725009653088790">"બૅટરી સેવર ઘેરી થીમની સુવિધા ચાલુ કરે છે, બૅકગ્રાઉન્ડ પ્રવૃત્તિ પ્રતિબંધિત કરે છે અને નોટિફિકેશન વિલંબે મોકલે છે."</string>
<string name="battery_low_percent_format" msgid="4276661262843170964">"<xliff:g id="PERCENTAGE">%s</xliff:g> બાકી"</string>
<string name="invalid_charger_title" msgid="938685362320735167">"USB મારફતે ચાર્જ કરી શકતા નથી"</string>
<string name="invalid_charger_text" msgid="2339310107232691577">"તમારા ઉપકરણ સાથે આવેલ ચાર્જરનો ઉપયોગ કરો"</string>
<string name="battery_saver_confirmation_title" msgid="1234998463717398453">"બૅટરી સેવર ચાલુ કરીએ?"</string>
<string name="battery_saver_confirmation_title_generic" msgid="2299231884234959849">"બૅટરી સેવર વિશે"</string>
<string name="battery_saver_confirmation_ok" msgid="5042136476802816494">"ચાલુ કરો"</string>
- <string name="battery_saver_start_action" msgid="4553256017945469937">"બૅટરી સેવર ચાલુ કરો"</string>
+ <string name="battery_saver_start_action" msgid="8353766979886287140">"ચાલુ કરો"</string>
+ <string name="battery_saver_dismiss_action" msgid="7199342621040014738">"ના, આભાર"</string>
<string name="status_bar_settings_auto_rotation" msgid="8329080442278431708">"ઑટો રોટેટ સ્ક્રીન"</string>
<string name="usb_device_permission_prompt" msgid="4414719028369181772">"<xliff:g id="USB_DEVICE">%2$s</xliff:g>ના ઍક્સેસ માટે <xliff:g id="APPLICATION">%1$s</xliff:g>ને મંજૂરી આપીએ?"</string>
<string name="usb_device_permission_prompt_warn" msgid="2309129784984063656">"<xliff:g id="APPLICATION">%1$s</xliff:g>ને <xliff:g id="USB_DEVICE">%2$s</xliff:g> ઍક્સેસ કરવાની મંજૂરી આપીએ?\nઆ ઍપને રેકૉર્ડ કરવાની પરવાનગી આપવામાં આવી નથી પરંતુ તે આ USB ડિવાઇસ મારફત ઑડિયો કૅપ્ચર કરી શકે છે."</string>
@@ -133,8 +131,7 @@
<string name="biometric_dialog_face_icon_description_authenticated" msgid="2242167416140740920">"ચહેરાનું પ્રમાણીકરણ થયું"</string>
<string name="biometric_dialog_face_icon_description_confirmed" msgid="7918067993953940778">"પુષ્ટિ કરી"</string>
<string name="biometric_dialog_tap_confirm" msgid="9166350738859143358">"પરીક્ષણ પૂર્ણ કરવા કન્ફર્મ કરોને ટૅપ કરો"</string>
- <!-- no translation found for biometric_dialog_tap_confirm_with_face (1597899891472340950) -->
- <skip />
+ <string name="biometric_dialog_tap_confirm_with_face" msgid="1597899891472340950">"તમારા ચહેરા વડે અનલૉક કર્યું. આગળ વધવા માટે ટૅપ કરો."</string>
<string name="biometric_dialog_authenticated" msgid="7337147327545272484">"પ્રમાણિત"</string>
<string name="biometric_dialog_use_pin" msgid="8385294115283000709">"પિનનો ઉપયોગ કરો"</string>
<string name="biometric_dialog_use_pattern" msgid="2315593393167211194">"પૅટર્નનો ઉપયોગ કરો"</string>
@@ -462,8 +459,8 @@
<string name="wallet_secondary_label_device_locked" msgid="5175862019125370506">"ઉપયોગ કરવા માટે અનલૉક કરો"</string>
<string name="wallet_error_generic" msgid="257704570182963611">"તમારા કાર્ડની માહિતી મેળવવામાં સમસ્યા આવી હતી, કૃપા કરીને થોડા સમય પછી ફરી પ્રયાસ કરો"</string>
<string name="wallet_lockscreen_settings_label" msgid="3539105300870383570">"લૉક સ્ક્રીનના સેટિંગ"</string>
- <string name="qr_code_scanner_title" msgid="5660820608548306581">"QR કોડ"</string>
- <string name="qr_code_scanner_description" msgid="7937603775306661863">"સ્કૅન કરવા માટે ટૅપ કરો"</string>
+ <!-- no translation found for qr_code_scanner_title (5290201053875420785) -->
+ <skip />
<string name="status_bar_work" msgid="5238641949837091056">"ઑફિસની પ્રોફાઇલ"</string>
<string name="status_bar_airplane" msgid="4848702508684541009">"એરપ્લેન મોડ"</string>
<string name="zen_alarm_warning" msgid="7844303238486849503">"તમે <xliff:g id="WHEN">%1$s</xliff:g> એ તમારો આગલો એલાર્મ સાંભળશો નહીં"</string>
@@ -827,6 +824,7 @@
<string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"નવા ડિવાઇસ સાથે જોડાણ કરો"</string>
<string name="media_output_dialog_launch_app_text" msgid="1527413319632586259">"આ સત્ર કાસ્ટ કરવા માટે, કૃપા કરીને ઍપ ખોલો."</string>
<string name="media_output_dialog_unknown_launch_app_name" msgid="1084899329829371336">"અજાણી ઍપ"</string>
+ <string name="media_output_dialog_button_stop_casting" msgid="6581379537930199189">"કાસ્ટ કરવાનું રોકો"</string>
<string name="build_number_clip_data_label" msgid="3623176728412560914">"બિલ્ડ નંબર"</string>
<string name="build_number_copy_toast" msgid="877720921605503046">"બિલ્ડ નંબર ક્લિપબૉર્ડ પર કૉપિ કર્યો."</string>
<string name="basic_status" msgid="2315371112182658176">"વાતચીત ખોલો"</string>
@@ -916,7 +914,6 @@
<string name="dream_overlay_status_bar_wifi_off" msgid="4497069245055003582">"વાઇ-ફાઇ ઉપલબ્ધ નથી"</string>
<string name="dream_overlay_status_bar_priority_mode" msgid="5428462123314728739">"પ્રાધાન્યતા મોડ"</string>
<string name="dream_overlay_status_bar_alarm_set" msgid="566707328356590886">"અલાર્મ સેટ"</string>
- <string name="dream_overlay_status_bar_assistant_guest_mode_enabled" msgid="3715897096012469615">"Assistant અતિથિ મોડ ચાલુ કર્યો"</string>
<string name="dream_overlay_status_bar_camera_mic_off" msgid="3199425257833773569">"કૅમેરા અને માઇક બંધ છે"</string>
<string name="dream_overlay_status_bar_notification_indicator" msgid="8091389255691081711">"{count,plural, =1{# નોટિફિકેશન}one{# નોટિફિકેશન}other{# નોટિફિકેશન}}"</string>
</resources>
diff --git a/packages/SystemUI/res/values-hi/strings.xml b/packages/SystemUI/res/values-hi/strings.xml
index 27e5091..d7b9f32 100644
--- a/packages/SystemUI/res/values-hi/strings.xml
+++ b/packages/SystemUI/res/values-hi/strings.xml
@@ -20,19 +20,17 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_label" msgid="4811759950673118541">"सिस्टम यूआई"</string>
- <!-- no translation found for battery_low_title (5319680173344341779) -->
- <skip />
- <!-- no translation found for battery_low_description (3282977755476423966) -->
- <skip />
- <!-- no translation found for battery_low_intro (5148725009653088790) -->
- <skip />
+ <string name="battery_low_title" msgid="5319680173344341779">"क्या आपको बैटरी सेवर मोड चालू करना है?"</string>
+ <string name="battery_low_description" msgid="3282977755476423966">"आपकी बैटरी <xliff:g id="PERCENTAGE">%s</xliff:g> बची है. बैटरी सेवर मोड पर, गहरे रंग वाली थीम चालू होती है और बैकग्राउंड में चल रही गतिविधियों पर रोक लग जाती है. इसके अलावा, आपको सूचनाएं भी देरी से मिलती हैं."</string>
+ <string name="battery_low_intro" msgid="5148725009653088790">"बैटरी सेवर मोड पर, गहरे रंग वाली थीम चालू होती है और बैकग्राउंड में चल रही गतिविधियों पर रोक लग जाती है. इसके अलावा, आपको सूचनाएं भी देरी से मिलती हैं."</string>
<string name="battery_low_percent_format" msgid="4276661262843170964">"<xliff:g id="PERCENTAGE">%s</xliff:g> शेष"</string>
<string name="invalid_charger_title" msgid="938685362320735167">"यूएसबी के ज़रिए चार्ज नहीं किया जा सकता"</string>
<string name="invalid_charger_text" msgid="2339310107232691577">"अपने डिवाइस के साथ मिलने वाले चार्जर का इस्तेमाल करें"</string>
<string name="battery_saver_confirmation_title" msgid="1234998463717398453">"क्या आप बैटरी सेवर चालू करना चाहते हैं?"</string>
<string name="battery_saver_confirmation_title_generic" msgid="2299231884234959849">"बैटरी सेवर के बारे में"</string>
<string name="battery_saver_confirmation_ok" msgid="5042136476802816494">"चालू करें"</string>
- <string name="battery_saver_start_action" msgid="4553256017945469937">"बैटरी सेवर चालू करें"</string>
+ <string name="battery_saver_start_action" msgid="8353766979886287140">"चालू करें"</string>
+ <string name="battery_saver_dismiss_action" msgid="7199342621040014738">"रहने दें"</string>
<string name="status_bar_settings_auto_rotation" msgid="8329080442278431708">"स्क्रीन अपने आप घुमाना"</string>
<string name="usb_device_permission_prompt" msgid="4414719028369181772">"<xliff:g id="APPLICATION">%1$s</xliff:g> को <xliff:g id="USB_DEVICE">%2$s</xliff:g> के ऐक्सेस की अनुमति दें?"</string>
<string name="usb_device_permission_prompt_warn" msgid="2309129784984063656">"आप <xliff:g id="APPLICATION">%1$s</xliff:g> को <xliff:g id="USB_DEVICE">%2$s</xliff:g> ऐक्सेस करने की अनुमति देना चाहते हैं?\nइस ऐप्लिकेशन को रिकॉर्ड करने की अनुमति नहीं दी गई है. हालांकि, ऐप्लिकेशन इस यूएसबी डिवाइस से ऑडियो कैप्चर कर सकता है."</string>
@@ -133,8 +131,7 @@
<string name="biometric_dialog_face_icon_description_authenticated" msgid="2242167416140740920">"चेहरे की पुष्टि हो गई"</string>
<string name="biometric_dialog_face_icon_description_confirmed" msgid="7918067993953940778">"पुष्टि हो गई"</string>
<string name="biometric_dialog_tap_confirm" msgid="9166350738859143358">"\'पुष्टि करें\' पर टैप करके पूरा करें"</string>
- <!-- no translation found for biometric_dialog_tap_confirm_with_face (1597899891472340950) -->
- <skip />
+ <string name="biometric_dialog_tap_confirm_with_face" msgid="1597899891472340950">"आपके चेहरे से अनलॉक किया गया. जारी रखने के लिए टैप करें."</string>
<string name="biometric_dialog_authenticated" msgid="7337147327545272484">"पुष्टि हो गई"</string>
<string name="biometric_dialog_use_pin" msgid="8385294115283000709">"पिन इस्तेमाल करें"</string>
<string name="biometric_dialog_use_pattern" msgid="2315593393167211194">"पैटर्न इस्तेमाल करें"</string>
@@ -462,8 +459,8 @@
<string name="wallet_secondary_label_device_locked" msgid="5175862019125370506">"इस्तेमाल करने के लिए, डिवाइस अनलॉक करें"</string>
<string name="wallet_error_generic" msgid="257704570182963611">"आपके कार्ड की जानकारी पाने में कोई समस्या हुई है. कृपया बाद में कोशिश करें"</string>
<string name="wallet_lockscreen_settings_label" msgid="3539105300870383570">"लॉक स्क्रीन की सेटिंग"</string>
- <string name="qr_code_scanner_title" msgid="5660820608548306581">"क्यूआर कोड"</string>
- <string name="qr_code_scanner_description" msgid="7937603775306661863">"स्कैन करने के लिए टैप करें"</string>
+ <!-- no translation found for qr_code_scanner_title (5290201053875420785) -->
+ <skip />
<string name="status_bar_work" msgid="5238641949837091056">"वर्क प्रोफ़ाइल"</string>
<string name="status_bar_airplane" msgid="4848702508684541009">"हवाई जहाज़ मोड"</string>
<string name="zen_alarm_warning" msgid="7844303238486849503">"आपको <xliff:g id="WHEN">%1$s</xliff:g> पर अपना अगला अलार्म नहीं सुनाई देगा"</string>
@@ -827,6 +824,7 @@
<string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"नया डिवाइस जोड़ें"</string>
<string name="media_output_dialog_launch_app_text" msgid="1527413319632586259">"इस सेशन को कास्ट करने के लिए, कृपया ऐप्लिकेशन खोलें."</string>
<string name="media_output_dialog_unknown_launch_app_name" msgid="1084899329829371336">"अनजान ऐप्लिकेशन"</string>
+ <string name="media_output_dialog_button_stop_casting" msgid="6581379537930199189">"कास्टिंग करना रोकें"</string>
<string name="build_number_clip_data_label" msgid="3623176728412560914">"बिल्ड नंबर"</string>
<string name="build_number_copy_toast" msgid="877720921605503046">"बिल्ड नंबर को क्लिपबोर्ड पर कॉपी किया गया."</string>
<string name="basic_status" msgid="2315371112182658176">"ऐसी बातचीत जिसमें इंटरैक्शन डेटा मौजूद नहीं है"</string>
@@ -916,8 +914,6 @@
<string name="dream_overlay_status_bar_wifi_off" msgid="4497069245055003582">"वाई-फ़ाई उपलब्ध नहीं है"</string>
<string name="dream_overlay_status_bar_priority_mode" msgid="5428462123314728739">"प्राथमिकता मोड"</string>
<string name="dream_overlay_status_bar_alarm_set" msgid="566707328356590886">"अलार्म सेट किया गया"</string>
- <string name="dream_overlay_status_bar_assistant_guest_mode_enabled" msgid="3715897096012469615">"Assistant का मेहमान मोड चालू किया गया"</string>
<string name="dream_overlay_status_bar_camera_mic_off" msgid="3199425257833773569">"कैमरा और माइक बंद हैं"</string>
- <!-- no translation found for dream_overlay_status_bar_notification_indicator (8091389255691081711) -->
- <skip />
+ <string name="dream_overlay_status_bar_notification_indicator" msgid="8091389255691081711">"{count,plural, =1{# सूचना}one{# सूचना}other{# सूचनाएं}}"</string>
</resources>
diff --git a/packages/SystemUI/res/values-hr/strings.xml b/packages/SystemUI/res/values-hr/strings.xml
index d3905e7..77cf814 100644
--- a/packages/SystemUI/res/values-hr/strings.xml
+++ b/packages/SystemUI/res/values-hr/strings.xml
@@ -20,19 +20,17 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_label" msgid="4811759950673118541">"UI sustava"</string>
- <!-- no translation found for battery_low_title (5319680173344341779) -->
- <skip />
- <!-- no translation found for battery_low_description (3282977755476423966) -->
- <skip />
- <!-- no translation found for battery_low_intro (5148725009653088790) -->
- <skip />
+ <string name="battery_low_title" msgid="5319680173344341779">"Želite li uključiti štednju baterije?"</string>
+ <string name="battery_low_description" msgid="3282977755476423966">"Imate još <xliff:g id="PERCENTAGE">%s</xliff:g> baterije. Štednja baterije uključuje tamnu temu, ograničava aktivnosti u pozadini i odgađa obavijesti."</string>
+ <string name="battery_low_intro" msgid="5148725009653088790">"Štednja baterije uključuje tamnu temu, ograničava aktivnosti u pozadini i odgađa obavijesti."</string>
<string name="battery_low_percent_format" msgid="4276661262843170964">"Preostalo <xliff:g id="PERCENTAGE">%s</xliff:g>"</string>
<string name="invalid_charger_title" msgid="938685362320735167">"Punjenje putem USB-a nije moguće"</string>
<string name="invalid_charger_text" msgid="2339310107232691577">"Koristite punjač koji ste dobili s uređajem"</string>
<string name="battery_saver_confirmation_title" msgid="1234998463717398453">"Uključiti Štednju baterije?"</string>
<string name="battery_saver_confirmation_title_generic" msgid="2299231884234959849">"O Štednji baterije"</string>
<string name="battery_saver_confirmation_ok" msgid="5042136476802816494">"Uključi"</string>
- <string name="battery_saver_start_action" msgid="4553256017945469937">"Uključite Štednju baterije"</string>
+ <string name="battery_saver_start_action" msgid="8353766979886287140">"Uključi"</string>
+ <string name="battery_saver_dismiss_action" msgid="7199342621040014738">"Ne, hvala"</string>
<string name="status_bar_settings_auto_rotation" msgid="8329080442278431708">"Automatski zakreni zaslon"</string>
<string name="usb_device_permission_prompt" msgid="4414719028369181772">"Želite li dopustiti aplikaciji <xliff:g id="APPLICATION">%1$s</xliff:g> pristup uređaju <xliff:g id="USB_DEVICE">%2$s</xliff:g>?"</string>
<string name="usb_device_permission_prompt_warn" msgid="2309129784984063656">"Želite li dopustiti aplikaciji <xliff:g id="APPLICATION">%1$s</xliff:g> da pristupa uređaju <xliff:g id="USB_DEVICE">%2$s</xliff:g>?\nTa aplikacija nema dopuštenje za snimanje, no mogla bi primati zvuk putem tog USB uređaja."</string>
@@ -133,8 +131,7 @@
<string name="biometric_dialog_face_icon_description_authenticated" msgid="2242167416140740920">"Lice je autentificirano"</string>
<string name="biometric_dialog_face_icon_description_confirmed" msgid="7918067993953940778">"Potvrđeno"</string>
<string name="biometric_dialog_tap_confirm" msgid="9166350738859143358">"Dodirnite Potvrdi za dovršetak"</string>
- <!-- no translation found for biometric_dialog_tap_confirm_with_face (1597899891472340950) -->
- <skip />
+ <string name="biometric_dialog_tap_confirm_with_face" msgid="1597899891472340950">"Otključano vašim licem. Pritisnite da biste nastavili."</string>
<string name="biometric_dialog_authenticated" msgid="7337147327545272484">"Autentičnost provjerena"</string>
<string name="biometric_dialog_use_pin" msgid="8385294115283000709">"Koristite PIN"</string>
<string name="biometric_dialog_use_pattern" msgid="2315593393167211194">"Koristite uzorak"</string>
@@ -465,8 +462,7 @@
<string name="wallet_secondary_label_device_locked" msgid="5175862019125370506">"Otključajte da biste koristili"</string>
<string name="wallet_error_generic" msgid="257704570182963611">"Pojavio se problem prilikom dohvaćanja kartica, pokušajte ponovo kasnije"</string>
<string name="wallet_lockscreen_settings_label" msgid="3539105300870383570">"Postavke zaključanog zaslona"</string>
- <string name="qr_code_scanner_title" msgid="5660820608548306581">"QR kôd"</string>
- <string name="qr_code_scanner_description" msgid="7937603775306661863">"Dodirnite za skeniranje"</string>
+ <string name="qr_code_scanner_title" msgid="5290201053875420785">"Skeniraj QR kôd"</string>
<string name="status_bar_work" msgid="5238641949837091056">"Poslovni profil"</string>
<string name="status_bar_airplane" msgid="4848702508684541009">"Način rada u zrakoplovu"</string>
<string name="zen_alarm_warning" msgid="7844303238486849503">"Nećete čuti sljedeći alarm <xliff:g id="WHEN">%1$s</xliff:g>"</string>
@@ -833,6 +829,7 @@
<string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"Uparite novi uređaj"</string>
<string name="media_output_dialog_launch_app_text" msgid="1527413319632586259">"Da biste emitirali ovu sesiju, otvorite aplikaciju."</string>
<string name="media_output_dialog_unknown_launch_app_name" msgid="1084899329829371336">"Nepoznata aplikacija"</string>
+ <string name="media_output_dialog_button_stop_casting" msgid="6581379537930199189">"Zaustavi emitiranje"</string>
<string name="build_number_clip_data_label" msgid="3623176728412560914">"Broj međuverzije"</string>
<string name="build_number_copy_toast" msgid="877720921605503046">"Broj međuverzije kopiran je u međuspremnik."</string>
<string name="basic_status" msgid="2315371112182658176">"Otvoreni razgovor"</string>
@@ -923,7 +920,6 @@
<string name="dream_overlay_status_bar_wifi_off" msgid="4497069245055003582">"Wi‑Fi nije dostupan"</string>
<string name="dream_overlay_status_bar_priority_mode" msgid="5428462123314728739">"Prioritetni način rada"</string>
<string name="dream_overlay_status_bar_alarm_set" msgid="566707328356590886">"Alarm je postavljen"</string>
- <string name="dream_overlay_status_bar_assistant_guest_mode_enabled" msgid="3715897096012469615">"Omogućen je način rada za goste u Asistentu"</string>
<string name="dream_overlay_status_bar_camera_mic_off" msgid="3199425257833773569">"Fotoaparat i mikrofon su isključeni"</string>
<string name="dream_overlay_status_bar_notification_indicator" msgid="8091389255691081711">"{count,plural, =1{# obavijest}one{# obavijest}few{# obavijesti}other{# obavijesti}}"</string>
</resources>
diff --git a/packages/SystemUI/res/values-hu/strings.xml b/packages/SystemUI/res/values-hu/strings.xml
index 3b94d8f..f256bc1 100644
--- a/packages/SystemUI/res/values-hu/strings.xml
+++ b/packages/SystemUI/res/values-hu/strings.xml
@@ -20,19 +20,17 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_label" msgid="4811759950673118541">"Rendszer UI"</string>
- <!-- no translation found for battery_low_title (5319680173344341779) -->
- <skip />
- <!-- no translation found for battery_low_description (3282977755476423966) -->
- <skip />
- <!-- no translation found for battery_low_intro (5148725009653088790) -->
- <skip />
+ <string name="battery_low_title" msgid="5319680173344341779">"Bekapcsolja az Akkumulátorkímélő módot?"</string>
+ <string name="battery_low_description" msgid="3282977755476423966">"Az akkumulátor töltöttségi szintje <xliff:g id="PERCENTAGE">%s</xliff:g>. Az Akkumulátorkímélő mód bekapcsolja a Sötét témát, korlátozza a háttérbeli tevékenységeket, és késlelteti az értesítéseket."</string>
+ <string name="battery_low_intro" msgid="5148725009653088790">"Az Akkumulátorkímélő mód bekapcsolja a Sötét témát, korlátozza a háttérbeli tevékenységeket, és késlelteti az értesítéseket."</string>
<string name="battery_low_percent_format" msgid="4276661262843170964">"<xliff:g id="PERCENTAGE">%s</xliff:g> maradt"</string>
<string name="invalid_charger_title" msgid="938685362320735167">"Nem tölthető USB-n keresztül"</string>
<string name="invalid_charger_text" msgid="2339310107232691577">"Használja az eszközhöz kapott eredeti töltőt"</string>
<string name="battery_saver_confirmation_title" msgid="1234998463717398453">"Bekapcsolja az Akkumulátorkímélő módot?"</string>
<string name="battery_saver_confirmation_title_generic" msgid="2299231884234959849">"Az Akkumulátorkímélő módról"</string>
<string name="battery_saver_confirmation_ok" msgid="5042136476802816494">"Bekapcsolás"</string>
- <string name="battery_saver_start_action" msgid="4553256017945469937">"Akkumulátorkímélő mód bekapcsolása"</string>
+ <string name="battery_saver_start_action" msgid="8353766979886287140">"Bekapcsolás"</string>
+ <string name="battery_saver_dismiss_action" msgid="7199342621040014738">"Most nem"</string>
<string name="status_bar_settings_auto_rotation" msgid="8329080442278431708">"Képernyő automatikus forgatása"</string>
<string name="usb_device_permission_prompt" msgid="4414719028369181772">"Engedélyezi a(z) <xliff:g id="APPLICATION">%1$s</xliff:g> számára, hogy hozzáférjen a következőhöz: <xliff:g id="USB_DEVICE">%2$s</xliff:g>?"</string>
<string name="usb_device_permission_prompt_warn" msgid="2309129784984063656">"Lehetővé teszi a(z) <xliff:g id="APPLICATION">%1$s</xliff:g> alkalmazásnak, hogy hozzáférjen a következőhöz: <xliff:g id="USB_DEVICE">%2$s</xliff:g>?\nEz az alkalmazás nem rendelkezik rögzítési engedéllyel, de ezzel az USB-eszközzel képes a hangfelvételre."</string>
@@ -133,8 +131,7 @@
<string name="biometric_dialog_face_icon_description_authenticated" msgid="2242167416140740920">"Arc hitelesítve"</string>
<string name="biometric_dialog_face_icon_description_confirmed" msgid="7918067993953940778">"Megerősítve"</string>
<string name="biometric_dialog_tap_confirm" msgid="9166350738859143358">"Koppintson a Megerősítés lehetőségre"</string>
- <!-- no translation found for biometric_dialog_tap_confirm_with_face (1597899891472340950) -->
- <skip />
+ <string name="biometric_dialog_tap_confirm_with_face" msgid="1597899891472340950">"Zárolás feloldva arccal. Nyomja meg a folytatáshoz."</string>
<string name="biometric_dialog_authenticated" msgid="7337147327545272484">"Hitelesítve"</string>
<string name="biometric_dialog_use_pin" msgid="8385294115283000709">"PIN-kód használata"</string>
<string name="biometric_dialog_use_pattern" msgid="2315593393167211194">"Minta használata"</string>
@@ -462,8 +459,7 @@
<string name="wallet_secondary_label_device_locked" msgid="5175862019125370506">"Oldja fel a használathoz"</string>
<string name="wallet_error_generic" msgid="257704570182963611">"Probléma merült fel a kártyák lekérésekor, próbálja újra később"</string>
<string name="wallet_lockscreen_settings_label" msgid="3539105300870383570">"Lezárási képernyő beállításai"</string>
- <string name="qr_code_scanner_title" msgid="5660820608548306581">"QR-kód"</string>
- <string name="qr_code_scanner_description" msgid="7937603775306661863">"Koppintson a beolvasáshoz"</string>
+ <string name="qr_code_scanner_title" msgid="5290201053875420785">"QR-kód beolvasása"</string>
<string name="status_bar_work" msgid="5238641949837091056">"Munkahelyi profil"</string>
<string name="status_bar_airplane" msgid="4848702508684541009">"Repülős üzemmód"</string>
<string name="zen_alarm_warning" msgid="7844303238486849503">"Nem fogja hallani az ébresztést ekkor: <xliff:g id="WHEN">%1$s</xliff:g>"</string>
@@ -827,6 +823,7 @@
<string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"Új eszköz párosítása"</string>
<string name="media_output_dialog_launch_app_text" msgid="1527413319632586259">"A munkamenet átküldéséhez nyissa meg az alkalmazást."</string>
<string name="media_output_dialog_unknown_launch_app_name" msgid="1084899329829371336">"Ismeretlen alkalmazás"</string>
+ <string name="media_output_dialog_button_stop_casting" msgid="6581379537930199189">"Átküldés leállítása"</string>
<string name="build_number_clip_data_label" msgid="3623176728412560914">"Buildszám"</string>
<string name="build_number_copy_toast" msgid="877720921605503046">"Buildszám a vágólapra másolva."</string>
<string name="basic_status" msgid="2315371112182658176">"Beszélgetés megnyitása"</string>
@@ -916,7 +913,6 @@
<string name="dream_overlay_status_bar_wifi_off" msgid="4497069245055003582">"A Wi‑Fi nem áll rendelkezésre"</string>
<string name="dream_overlay_status_bar_priority_mode" msgid="5428462123314728739">"Prioritás mód"</string>
<string name="dream_overlay_status_bar_alarm_set" msgid="566707328356590886">"Ébresztő beállítva"</string>
- <string name="dream_overlay_status_bar_assistant_guest_mode_enabled" msgid="3715897096012469615">"A Segéd vendég módja engedélyezve"</string>
<string name="dream_overlay_status_bar_camera_mic_off" msgid="3199425257833773569">"A kamera és a mikrofon ki vannak kapcsolva"</string>
<string name="dream_overlay_status_bar_notification_indicator" msgid="8091389255691081711">"{count,plural, =1{# értesítés}other{# értesítés}}"</string>
</resources>
diff --git a/packages/SystemUI/res/values-hy/strings.xml b/packages/SystemUI/res/values-hy/strings.xml
index 488aa76..a4e3b82 100644
--- a/packages/SystemUI/res/values-hy/strings.xml
+++ b/packages/SystemUI/res/values-hy/strings.xml
@@ -20,19 +20,17 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_label" msgid="4811759950673118541">"Համակարգի ինտերֆեյս"</string>
- <!-- no translation found for battery_low_title (5319680173344341779) -->
- <skip />
- <!-- no translation found for battery_low_description (3282977755476423966) -->
- <skip />
- <!-- no translation found for battery_low_intro (5148725009653088790) -->
- <skip />
+ <string name="battery_low_title" msgid="5319680173344341779">"Միացնե՞լ մարտկոցի տնտեսման ռեժիմը"</string>
+ <string name="battery_low_description" msgid="3282977755476423966">"Մարտկոցի լիցքը՝ <xliff:g id="PERCENTAGE">%s</xliff:g>։ Մարտկոցի տնտեսման ռեժիմում միացվում է մուգ թեման, աշխատանքը ֆոնային ռեժիմում սահմանափակվում է, իսկ ծանուցումները՝ հետաձգվում։"</string>
+ <string name="battery_low_intro" msgid="5148725009653088790">"Մարտկոցի տնտեսման ռեժիմում միացվում է մուգ թեման, աշխատանքը ֆոնային ռեժիմում սահմանափակվում է, իսկ ծանուցումները՝ հետաձգվում։"</string>
<string name="battery_low_percent_format" msgid="4276661262843170964">"Մնաց <xliff:g id="PERCENTAGE">%s</xliff:g>"</string>
<string name="invalid_charger_title" msgid="938685362320735167">"Սարքը հնարավոր չէ լիցքավորել USB-ի միջոցով"</string>
<string name="invalid_charger_text" msgid="2339310107232691577">"Օգտագործեք սարքի լիցքավորիչը"</string>
<string name="battery_saver_confirmation_title" msgid="1234998463717398453">"Միացնե՞լ մարտկոցի տնտեսումը"</string>
<string name="battery_saver_confirmation_title_generic" msgid="2299231884234959849">"Մարտկոցի տնտեսման ռեժիմի մասին"</string>
<string name="battery_saver_confirmation_ok" msgid="5042136476802816494">"Միացնել"</string>
- <string name="battery_saver_start_action" msgid="4553256017945469937">"Միացնել մարտկոցի տնտեսումը"</string>
+ <string name="battery_saver_start_action" msgid="8353766979886287140">"Միացնել"</string>
+ <string name="battery_saver_dismiss_action" msgid="7199342621040014738">"Ոչ, շնորհակալություն"</string>
<string name="status_bar_settings_auto_rotation" msgid="8329080442278431708">"Ինքնապտտվող էկրան"</string>
<string name="usb_device_permission_prompt" msgid="4414719028369181772">"Թույլատրե՞լ <xliff:g id="APPLICATION">%1$s</xliff:g> հավելվածին օգտագործել <xliff:g id="USB_DEVICE">%2$s</xliff:g> լրասարքը։"</string>
<string name="usb_device_permission_prompt_warn" msgid="2309129784984063656">"Թույլատրե՞լ <xliff:g id="APPLICATION">%1$s</xliff:g> հավելվածին օգտագործել <xliff:g id="USB_DEVICE">%2$s</xliff:g>ը։\nՀավելվածը ձայնագրելու թույլտվություն չունի, սակայն կկարողանա գրանցել ձայնն այս USB սարքի միջոցով։"</string>
@@ -133,8 +131,7 @@
<string name="biometric_dialog_face_icon_description_authenticated" msgid="2242167416140740920">"Դեմքը ճանաչվեց"</string>
<string name="biometric_dialog_face_icon_description_confirmed" msgid="7918067993953940778">"Հաստատվեց"</string>
<string name="biometric_dialog_tap_confirm" msgid="9166350738859143358">"Ավարտելու համար հպեք «Հաստատել»"</string>
- <!-- no translation found for biometric_dialog_tap_confirm_with_face (1597899891472340950) -->
- <skip />
+ <string name="biometric_dialog_tap_confirm_with_face" msgid="1597899891472340950">"Ապակողպվեց դեմքով։ Սեղմեք՝ շարունակելու համար։"</string>
<string name="biometric_dialog_authenticated" msgid="7337147327545272484">"Նույնականացված է"</string>
<string name="biometric_dialog_use_pin" msgid="8385294115283000709">"Օգտագործել PIN կոդ"</string>
<string name="biometric_dialog_use_pattern" msgid="2315593393167211194">"Օգտագործել նախշ"</string>
@@ -462,8 +459,8 @@
<string name="wallet_secondary_label_device_locked" msgid="5175862019125370506">"Ապակողպել՝ օգտագործելու համար"</string>
<string name="wallet_error_generic" msgid="257704570182963611">"Չհաջողվեց բեռնել քարտերը։ Նորից փորձեք։"</string>
<string name="wallet_lockscreen_settings_label" msgid="3539105300870383570">"Կողպէկրանի կարգավորումներ"</string>
- <string name="qr_code_scanner_title" msgid="5660820608548306581">"QR կոդ"</string>
- <string name="qr_code_scanner_description" msgid="7937603775306661863">"Հպեք՝ սկանավորելու համար"</string>
+ <!-- no translation found for qr_code_scanner_title (5290201053875420785) -->
+ <skip />
<string name="status_bar_work" msgid="5238641949837091056">"Android for Work-ի պրոֆիլ"</string>
<string name="status_bar_airplane" msgid="4848702508684541009">"Ավիառեժիմ"</string>
<string name="zen_alarm_warning" msgid="7844303238486849503">"Ժամը <xliff:g id="WHEN">%1$s</xliff:g>-ի զարթուցիչը չի զանգի"</string>
@@ -827,6 +824,7 @@
<string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"Նոր սարքի զուգակցում"</string>
<string name="media_output_dialog_launch_app_text" msgid="1527413319632586259">"Այս աշխատաշրջանը հեռարձակելու համար բացեք հավելվածը"</string>
<string name="media_output_dialog_unknown_launch_app_name" msgid="1084899329829371336">"Անհայտ հավելված"</string>
+ <string name="media_output_dialog_button_stop_casting" msgid="6581379537930199189">"Դադարեցնել հեռարձակումը"</string>
<string name="build_number_clip_data_label" msgid="3623176728412560914">"Կառուցման համարը"</string>
<string name="build_number_copy_toast" msgid="877720921605503046">"Կառուցման համարը պատճենվեց սեղմատախտակին։"</string>
<string name="basic_status" msgid="2315371112182658176">"Բաց զրույց"</string>
@@ -916,8 +914,6 @@
<string name="dream_overlay_status_bar_wifi_off" msgid="4497069245055003582">"Wi‑Fi-ը հասանելի չէ"</string>
<string name="dream_overlay_status_bar_priority_mode" msgid="5428462123314728739">"Առաջնահերթության ռեժիմ"</string>
<string name="dream_overlay_status_bar_alarm_set" msgid="566707328356590886">"Զարթուցիչը դրված է"</string>
- <string name="dream_overlay_status_bar_assistant_guest_mode_enabled" msgid="3715897096012469615">"Օգնականի հյուրի ռեժիմը միացված է"</string>
<string name="dream_overlay_status_bar_camera_mic_off" msgid="3199425257833773569">"Տեսախցիկը և խոսափողն անջատված են"</string>
- <!-- no translation found for dream_overlay_status_bar_notification_indicator (8091389255691081711) -->
- <skip />
+ <string name="dream_overlay_status_bar_notification_indicator" msgid="8091389255691081711">"{count,plural, =1{# ծանուցում}one{# ծանուցում}other{# ծանուցում}}"</string>
</resources>
diff --git a/packages/SystemUI/res/values-in/strings.xml b/packages/SystemUI/res/values-in/strings.xml
index 0913166..c9ce287 100644
--- a/packages/SystemUI/res/values-in/strings.xml
+++ b/packages/SystemUI/res/values-in/strings.xml
@@ -20,19 +20,17 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_label" msgid="4811759950673118541">"UI Sistem"</string>
- <!-- no translation found for battery_low_title (5319680173344341779) -->
- <skip />
- <!-- no translation found for battery_low_description (3282977755476423966) -->
- <skip />
- <!-- no translation found for battery_low_intro (5148725009653088790) -->
- <skip />
+ <string name="battery_low_title" msgid="5319680173344341779">"Aktifkan Penghemat Baterai?"</string>
+ <string name="battery_low_description" msgid="3282977755476423966">"Daya baterai tersisa <xliff:g id="PERCENTAGE">%s</xliff:g>. Penghemat Baterai akan mengaktifkan Tema gelap, membatasi aktivitas latar belakang, dan menunda notifikasi."</string>
+ <string name="battery_low_intro" msgid="5148725009653088790">"Penghemat Baterai akan mengaktifkan Tema gelap, membatasi aktivitas latar belakang, dan menunda notifikasi."</string>
<string name="battery_low_percent_format" msgid="4276661262843170964">"Tersisa <xliff:g id="PERCENTAGE">%s</xliff:g>"</string>
<string name="invalid_charger_title" msgid="938685362320735167">"Tidak dapat mengisi daya melalui USB"</string>
<string name="invalid_charger_text" msgid="2339310107232691577">"Gunakan pengisi daya yang disertakan dengan perangkat"</string>
<string name="battery_saver_confirmation_title" msgid="1234998463717398453">"Aktifkan Penghemat Baterai?"</string>
<string name="battery_saver_confirmation_title_generic" msgid="2299231884234959849">"Tentang Penghemat Baterai"</string>
<string name="battery_saver_confirmation_ok" msgid="5042136476802816494">"Aktifkan"</string>
- <string name="battery_saver_start_action" msgid="4553256017945469937">"Aktifkan Penghemat Baterai"</string>
+ <string name="battery_saver_start_action" msgid="8353766979886287140">"Aktifkan"</string>
+ <string name="battery_saver_dismiss_action" msgid="7199342621040014738">"Lain kali"</string>
<string name="status_bar_settings_auto_rotation" msgid="8329080442278431708">"Putar layar otomatis"</string>
<string name="usb_device_permission_prompt" msgid="4414719028369181772">"Izinkan <xliff:g id="APPLICATION">%1$s</xliff:g> mengakses <xliff:g id="USB_DEVICE">%2$s</xliff:g>?"</string>
<string name="usb_device_permission_prompt_warn" msgid="2309129784984063656">"Izinkan <xliff:g id="APPLICATION">%1$s</xliff:g> mengakses <xliff:g id="USB_DEVICE">%2$s</xliff:g>?\nAplikasi ini belum diberi izin merekam, tetapi dapat merekam audio melalui perangkat USB ini."</string>
@@ -133,8 +131,7 @@
<string name="biometric_dialog_face_icon_description_authenticated" msgid="2242167416140740920">"Wajah diautentikasi"</string>
<string name="biometric_dialog_face_icon_description_confirmed" msgid="7918067993953940778">"Dikonfirmasi"</string>
<string name="biometric_dialog_tap_confirm" msgid="9166350738859143358">"Ketuk Konfirmasi untuk menyelesaikan"</string>
- <!-- no translation found for biometric_dialog_tap_confirm_with_face (1597899891472340950) -->
- <skip />
+ <string name="biometric_dialog_tap_confirm_with_face" msgid="1597899891472340950">"Kunci dibuka dengan wajah Anda. Tekan untuk melanjutkan."</string>
<string name="biometric_dialog_authenticated" msgid="7337147327545272484">"Diautentikasi"</string>
<string name="biometric_dialog_use_pin" msgid="8385294115283000709">"Gunakan PIN"</string>
<string name="biometric_dialog_use_pattern" msgid="2315593393167211194">"Gunakan pola"</string>
@@ -462,8 +459,8 @@
<string name="wallet_secondary_label_device_locked" msgid="5175862019125370506">"Buka kunci untuk menggunakan"</string>
<string name="wallet_error_generic" msgid="257704570182963611">"Terjadi masalah saat mendapatkan kartu Anda, coba lagi nanti"</string>
<string name="wallet_lockscreen_settings_label" msgid="3539105300870383570">"Setelan layar kunci"</string>
- <string name="qr_code_scanner_title" msgid="5660820608548306581">"Kode QR"</string>
- <string name="qr_code_scanner_description" msgid="7937603775306661863">"Ketuk untuk memindai"</string>
+ <!-- no translation found for qr_code_scanner_title (5290201053875420785) -->
+ <skip />
<string name="status_bar_work" msgid="5238641949837091056">"Profil kerja"</string>
<string name="status_bar_airplane" msgid="4848702508684541009">"Mode pesawat"</string>
<string name="zen_alarm_warning" msgid="7844303238486849503">"Anda tidak akan mendengar alarm berikutnya <xliff:g id="WHEN">%1$s</xliff:g>"</string>
@@ -827,6 +824,7 @@
<string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"Sambungkan perangkat baru"</string>
<string name="media_output_dialog_launch_app_text" msgid="1527413319632586259">"Buka aplikasi untuk mentransmisikan sesi ini."</string>
<string name="media_output_dialog_unknown_launch_app_name" msgid="1084899329829371336">"Aplikasi tidak dikenal"</string>
+ <string name="media_output_dialog_button_stop_casting" msgid="6581379537930199189">"Hentikan transmisi"</string>
<string name="build_number_clip_data_label" msgid="3623176728412560914">"Nomor build"</string>
<string name="build_number_copy_toast" msgid="877720921605503046">"Nomor versi disalin ke papan klip."</string>
<string name="basic_status" msgid="2315371112182658176">"Membuka percakapan"</string>
@@ -916,8 +914,6 @@
<string name="dream_overlay_status_bar_wifi_off" msgid="4497069245055003582">"Wi‑Fi tidak tersedia"</string>
<string name="dream_overlay_status_bar_priority_mode" msgid="5428462123314728739">"Mode prioritas"</string>
<string name="dream_overlay_status_bar_alarm_set" msgid="566707328356590886">"Alarm disetel"</string>
- <string name="dream_overlay_status_bar_assistant_guest_mode_enabled" msgid="3715897096012469615">"Mode Tamu Asisten diaktifkan"</string>
<string name="dream_overlay_status_bar_camera_mic_off" msgid="3199425257833773569">"Kamera dan mikrofon nonaktif"</string>
- <!-- no translation found for dream_overlay_status_bar_notification_indicator (8091389255691081711) -->
- <skip />
+ <string name="dream_overlay_status_bar_notification_indicator" msgid="8091389255691081711">"{count,plural, =1{# notifikasi}other{# notifikasi}}"</string>
</resources>
diff --git a/packages/SystemUI/res/values-is/strings.xml b/packages/SystemUI/res/values-is/strings.xml
index cddb8f8..78d2ecf 100644
--- a/packages/SystemUI/res/values-is/strings.xml
+++ b/packages/SystemUI/res/values-is/strings.xml
@@ -20,19 +20,17 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_label" msgid="4811759950673118541">"Kerfisviðmót"</string>
- <!-- no translation found for battery_low_title (5319680173344341779) -->
- <skip />
- <!-- no translation found for battery_low_description (3282977755476423966) -->
- <skip />
- <!-- no translation found for battery_low_intro (5148725009653088790) -->
- <skip />
+ <string name="battery_low_title" msgid="5319680173344341779">"Kveikja á rafhlöðusparnaði?"</string>
+ <string name="battery_low_description" msgid="3282977755476423966">"<xliff:g id="PERCENTAGE">%s</xliff:g> rafhlöðuhleðsla eftir. Rafhlöðusparnaður kveikir á dökku þema, dregur úr bakgrunnsvirkni og seinkar tilkynningum."</string>
+ <string name="battery_low_intro" msgid="5148725009653088790">"Rafhlöðusparnaður kveikir á dökku þema, dregur úr bakgrunnsvirkni og seinkar tilkynningum."</string>
<string name="battery_low_percent_format" msgid="4276661262843170964">"<xliff:g id="PERCENTAGE">%s</xliff:g> eftir"</string>
<string name="invalid_charger_title" msgid="938685362320735167">"Ekki er hægt að hlaða í gegnum USB"</string>
<string name="invalid_charger_text" msgid="2339310107232691577">"Notaðu hleðslutækið sem fylgdi tækinu þínu"</string>
<string name="battery_saver_confirmation_title" msgid="1234998463717398453">"Kveikja á rafhlöðusparnaði?"</string>
<string name="battery_saver_confirmation_title_generic" msgid="2299231884234959849">"Um rafhlöðusparnað"</string>
<string name="battery_saver_confirmation_ok" msgid="5042136476802816494">"Kveikja"</string>
- <string name="battery_saver_start_action" msgid="4553256017945469937">"Kveikja á rafhlöðusparnaði"</string>
+ <string name="battery_saver_start_action" msgid="8353766979886287140">"Kveikja"</string>
+ <string name="battery_saver_dismiss_action" msgid="7199342621040014738">"Nei, takk"</string>
<string name="status_bar_settings_auto_rotation" msgid="8329080442278431708">"Snúa skjá sjálfkrafa"</string>
<string name="usb_device_permission_prompt" msgid="4414719028369181772">"Viltu veita <xliff:g id="APPLICATION">%1$s</xliff:g> aðgang að <xliff:g id="USB_DEVICE">%2$s</xliff:g>?"</string>
<string name="usb_device_permission_prompt_warn" msgid="2309129784984063656">"Viltu veita <xliff:g id="APPLICATION">%1$s</xliff:g> aðgang að <xliff:g id="USB_DEVICE">%2$s</xliff:g>?\nÞetta forrit hefur ekki fengið heimild fyrir upptöku en gæti tekið upp hljóð í gegnum þetta USB-tæki."</string>
@@ -133,8 +131,7 @@
<string name="biometric_dialog_face_icon_description_authenticated" msgid="2242167416140740920">"Andlit staðfest"</string>
<string name="biometric_dialog_face_icon_description_confirmed" msgid="7918067993953940778">"Staðfest"</string>
<string name="biometric_dialog_tap_confirm" msgid="9166350738859143358">"Ýttu á „Staðfesta“ til að ljúka"</string>
- <!-- no translation found for biometric_dialog_tap_confirm_with_face (1597899891472340950) -->
- <skip />
+ <string name="biometric_dialog_tap_confirm_with_face" msgid="1597899891472340950">"Opnað með andlitinu á þér. Ýttu til að halda áfram."</string>
<string name="biometric_dialog_authenticated" msgid="7337147327545272484">"Auðkennt"</string>
<string name="biometric_dialog_use_pin" msgid="8385294115283000709">"Nota PIN-númer"</string>
<string name="biometric_dialog_use_pattern" msgid="2315593393167211194">"Nota mynstur"</string>
@@ -462,8 +459,8 @@
<string name="wallet_secondary_label_device_locked" msgid="5175862019125370506">"Taktu úr lás til að nota"</string>
<string name="wallet_error_generic" msgid="257704570182963611">"Vandamál kom upp við að sækja kortin þín. Reyndu aftur síðar"</string>
<string name="wallet_lockscreen_settings_label" msgid="3539105300870383570">"Stillingar fyrir læstan skjá"</string>
- <string name="qr_code_scanner_title" msgid="5660820608548306581">"QR-kóði"</string>
- <string name="qr_code_scanner_description" msgid="7937603775306661863">"Ýttu til að skanna"</string>
+ <!-- no translation found for qr_code_scanner_title (5290201053875420785) -->
+ <skip />
<string name="status_bar_work" msgid="5238641949837091056">"Vinnusnið"</string>
<string name="status_bar_airplane" msgid="4848702508684541009">"Flugstilling"</string>
<string name="zen_alarm_warning" msgid="7844303238486849503">"Ekki mun heyrast í vekjaranum <xliff:g id="WHEN">%1$s</xliff:g>"</string>
@@ -827,6 +824,7 @@
<string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"Para nýtt tæki"</string>
<string name="media_output_dialog_launch_app_text" msgid="1527413319632586259">"Opnaðu forritið til að senda þessa lotu út."</string>
<string name="media_output_dialog_unknown_launch_app_name" msgid="1084899329829371336">"Óþekkt forrit"</string>
+ <string name="media_output_dialog_button_stop_casting" msgid="6581379537930199189">"Stöðva útsendingu"</string>
<string name="build_number_clip_data_label" msgid="3623176728412560914">"Útgáfunúmer smíðar"</string>
<string name="build_number_copy_toast" msgid="877720921605503046">"Útgáfunúmer smíðar afritað á klippiborð."</string>
<string name="basic_status" msgid="2315371112182658176">"Opna samtal"</string>
@@ -916,8 +914,6 @@
<string name="dream_overlay_status_bar_wifi_off" msgid="4497069245055003582">"WiFi ekki tiltækt"</string>
<string name="dream_overlay_status_bar_priority_mode" msgid="5428462123314728739">"Forgangsstilling"</string>
<string name="dream_overlay_status_bar_alarm_set" msgid="566707328356590886">"Vekjari stilltur"</string>
- <string name="dream_overlay_status_bar_assistant_guest_mode_enabled" msgid="3715897096012469615">"Kveikt á gestastillingu Hjálpara"</string>
<string name="dream_overlay_status_bar_camera_mic_off" msgid="3199425257833773569">"Slökkt á myndavél og hljóðnema"</string>
- <!-- no translation found for dream_overlay_status_bar_notification_indicator (8091389255691081711) -->
- <skip />
+ <string name="dream_overlay_status_bar_notification_indicator" msgid="8091389255691081711">"{count,plural, =1{# tilkynning}one{# tilkynning}other{# tilkynningar}}"</string>
</resources>
diff --git a/packages/SystemUI/res/values-it/strings.xml b/packages/SystemUI/res/values-it/strings.xml
index ed125cd..9b0f917 100644
--- a/packages/SystemUI/res/values-it/strings.xml
+++ b/packages/SystemUI/res/values-it/strings.xml
@@ -20,19 +20,17 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_label" msgid="4811759950673118541">"UI sistema"</string>
- <!-- no translation found for battery_low_title (5319680173344341779) -->
- <skip />
- <!-- no translation found for battery_low_description (3282977755476423966) -->
- <skip />
- <!-- no translation found for battery_low_intro (5148725009653088790) -->
- <skip />
+ <string name="battery_low_title" msgid="5319680173344341779">"Vuoi attivare il risparmio energetico?"</string>
+ <string name="battery_low_description" msgid="3282977755476423966">"Batteria rimanente: <xliff:g id="PERCENTAGE">%s</xliff:g>. Il risparmio energetico attiva il tema scuro, limita l\'attività in background e ritarda le notifiche."</string>
+ <string name="battery_low_intro" msgid="5148725009653088790">"Il risparmio energetico attiva il tema scuro, limita l\'attività in background e ritarda le notifiche."</string>
<string name="battery_low_percent_format" msgid="4276661262843170964">"<xliff:g id="PERCENTAGE">%s</xliff:g> rimanente"</string>
<string name="invalid_charger_title" msgid="938685362320735167">"Impossibile ricaricare tramite USB"</string>
<string name="invalid_charger_text" msgid="2339310107232691577">"Utilizza il caricabatterie fornito in dotazione con il dispositivo"</string>
<string name="battery_saver_confirmation_title" msgid="1234998463717398453">"Attivare Risparmio energetico?"</string>
<string name="battery_saver_confirmation_title_generic" msgid="2299231884234959849">"Informazioni su Risparmio energetico"</string>
<string name="battery_saver_confirmation_ok" msgid="5042136476802816494">"Attiva"</string>
- <string name="battery_saver_start_action" msgid="4553256017945469937">"Attiva Risparmio energetico"</string>
+ <string name="battery_saver_start_action" msgid="8353766979886287140">"Attiva"</string>
+ <string name="battery_saver_dismiss_action" msgid="7199342621040014738">"No, grazie"</string>
<string name="status_bar_settings_auto_rotation" msgid="8329080442278431708">"Rotazione automatica schermo"</string>
<string name="usb_device_permission_prompt" msgid="4414719028369181772">"Consentire a <xliff:g id="APPLICATION">%1$s</xliff:g> di accedere a <xliff:g id="USB_DEVICE">%2$s</xliff:g>?"</string>
<string name="usb_device_permission_prompt_warn" msgid="2309129784984063656">"Vuoi consentire all\'app <xliff:g id="APPLICATION">%1$s</xliff:g> di accedere a <xliff:g id="USB_DEVICE">%2$s</xliff:g>?\nA questa app non è stata concessa l\'autorizzazione di registrazione, ma l\'app potrebbe acquisire l\'audio tramite questo dispositivo USB."</string>
@@ -133,8 +131,7 @@
<string name="biometric_dialog_face_icon_description_authenticated" msgid="2242167416140740920">"Volto autenticato"</string>
<string name="biometric_dialog_face_icon_description_confirmed" msgid="7918067993953940778">"Confermato"</string>
<string name="biometric_dialog_tap_confirm" msgid="9166350738859143358">"Tocca Conferma per completare"</string>
- <!-- no translation found for biometric_dialog_tap_confirm_with_face (1597899891472340950) -->
- <skip />
+ <string name="biometric_dialog_tap_confirm_with_face" msgid="1597899891472340950">"Dispositivo sbloccato con il volto. Premi per continuare."</string>
<string name="biometric_dialog_authenticated" msgid="7337147327545272484">"Autenticazione eseguita"</string>
<string name="biometric_dialog_use_pin" msgid="8385294115283000709">"Utilizza PIN"</string>
<string name="biometric_dialog_use_pattern" msgid="2315593393167211194">"Usa sequenza"</string>
@@ -205,8 +202,8 @@
<string name="accessibility_clear_all" msgid="970525598287244592">"Cancella tutte le notifiche."</string>
<string name="notification_group_overflow_indicator" msgid="7605120293801012648">"+ <xliff:g id="NUMBER">%s</xliff:g>"</string>
<plurals name="notification_group_overflow_description" formatted="false" msgid="91483442850649192">
- <item quantity="one"><xliff:g id="NUMBER_1">%s</xliff:g> more notifications inside.</item>
<item quantity="other">Altre <xliff:g id="NUMBER_1">%s</xliff:g> notifiche nel gruppo.</item>
+ <item quantity="one"><xliff:g id="NUMBER_0">%s</xliff:g> altra notifica nel gruppo.</item>
</plurals>
<string name="accessibility_rotation_lock_on_landscape" msgid="936972553861524360">"Lo schermo è bloccato in orientamento orizzontale."</string>
<string name="accessibility_rotation_lock_on_portrait" msgid="2356633398683813837">"Lo schermo è bloccato in orientamento verticale."</string>
@@ -255,8 +252,8 @@
<string name="quick_settings_hotspot_secondary_label_transient" msgid="7585604088079160564">"Attivazione…"</string>
<string name="quick_settings_hotspot_secondary_label_data_saver_enabled" msgid="1280433136266439372">"Risp. dati attivo"</string>
<plurals name="quick_settings_hotspot_secondary_label_num_devices" formatted="false" msgid="3142308865165871976">
- <item quantity="one">%d devices</item>
<item quantity="other">%d dispositivi</item>
+ <item quantity="one">%d dispositivo</item>
</plurals>
<string name="quick_settings_flashlight_label" msgid="4904634272006284185">"Torcia"</string>
<string name="quick_settings_flashlight_camera_in_use" msgid="4820591564526512571">"Fotocamera in uso"</string>
@@ -339,8 +336,8 @@
<string name="user_add_user_message_short" msgid="2599370307878014791">"Il nuovo utente, una volta aggiunto, deve impostare il proprio spazio.\n\nQualsiasi utente può aggiornare le app per tutti gli altri."</string>
<string name="user_limit_reached_title" msgid="2429229448830346057">"Limite di utenti raggiunto"</string>
<plurals name="user_limit_reached_message" formatted="false" msgid="2573535787802908398">
- <item quantity="one">You can add up to <xliff:g id="COUNT">%d</xliff:g> users.</item>
<item quantity="other">Puoi aggiungere fino a <xliff:g id="COUNT">%d</xliff:g> utenti.</item>
+ <item quantity="one">È possibile creare un solo utente.</item>
</plurals>
<string name="user_remove_user_title" msgid="9124124694835811874">"Rimuovere l\'utente?"</string>
<string name="user_remove_user_message" msgid="6702834122128031833">"Tutte le app e i dati di questo utente verranno eliminati."</string>
@@ -462,8 +459,7 @@
<string name="wallet_secondary_label_device_locked" msgid="5175862019125370506">"Sblocca per usare"</string>
<string name="wallet_error_generic" msgid="257704570182963611">"Si è verificato un problema durante il recupero delle tue carte. Riprova più tardi."</string>
<string name="wallet_lockscreen_settings_label" msgid="3539105300870383570">"Impostazioni schermata di blocco"</string>
- <string name="qr_code_scanner_title" msgid="5660820608548306581">"Codice QR"</string>
- <string name="qr_code_scanner_description" msgid="7937603775306661863">"Tocca per scansionare"</string>
+ <string name="qr_code_scanner_title" msgid="5290201053875420785">"Scansiona codice QR"</string>
<string name="status_bar_work" msgid="5238641949837091056">"Profilo di lavoro"</string>
<string name="status_bar_airplane" msgid="4848702508684541009">"Modalità aereo"</string>
<string name="zen_alarm_warning" msgid="7844303238486849503">"Non sentirai la tua prossima sveglia <xliff:g id="WHEN">%1$s</xliff:g>"</string>
@@ -528,12 +524,12 @@
<string name="snooze_undo" msgid="2738844148845992103">"Annulla"</string>
<string name="snoozed_for_time" msgid="7586689374860469469">"Posticipato di <xliff:g id="TIME_AMOUNT">%1$s</xliff:g>"</string>
<plurals name="snoozeHourOptions" formatted="false" msgid="2066838694120718170">
- <item quantity="one">%d hours</item>
<item quantity="other">%d ore</item>
+ <item quantity="one">%d ora</item>
</plurals>
<plurals name="snoozeMinuteOptions" formatted="false" msgid="8998483159208055980">
- <item quantity="one">%d minutes</item>
<item quantity="other">%d minuti</item>
+ <item quantity="one">%d minuto</item>
</plurals>
<string name="battery_detail_switch_title" msgid="6940976502957380405">"Risparmio energetico"</string>
<string name="keyboard_key_button_template" msgid="8005673627272051429">"Pulsante <xliff:g id="NAME">%1$s</xliff:g>"</string>
@@ -756,8 +752,8 @@
<string name="quick_controls_title" msgid="6839108006171302273">"Controllo dispositivi"</string>
<string name="controls_providers_title" msgid="6879775889857085056">"Scegli un\'app per aggiungere controlli"</string>
<plurals name="controls_number_of_favorites" formatted="false" msgid="1057347832073807380">
- <item quantity="one"><xliff:g id="NUMBER_1">%s</xliff:g> controlli aggiunti.</item>
<item quantity="other"><xliff:g id="NUMBER_1">%s</xliff:g> controlli aggiunti.</item>
+ <item quantity="one"><xliff:g id="NUMBER_0">%s</xliff:g> controllo aggiunto.</item>
</plurals>
<string name="controls_removed" msgid="3731789252222856959">"Rimosso"</string>
<string name="accessibility_control_favorite" msgid="8694362691985545985">"Aggiunto ai preferiti"</string>
@@ -827,6 +823,7 @@
<string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"Accoppia nuovo dispositivo"</string>
<string name="media_output_dialog_launch_app_text" msgid="1527413319632586259">"Per trasmettere questa sessione devi aprire l\'app."</string>
<string name="media_output_dialog_unknown_launch_app_name" msgid="1084899329829371336">"App sconosciuta"</string>
+ <string name="media_output_dialog_button_stop_casting" msgid="6581379537930199189">"Interrompi trasmissione"</string>
<string name="build_number_clip_data_label" msgid="3623176728412560914">"Numero build"</string>
<string name="build_number_copy_toast" msgid="877720921605503046">"Numero build copiato negli appunti."</string>
<string name="basic_status" msgid="2315371112182658176">"Apri conversazione"</string>
@@ -896,8 +893,8 @@
<string name="qs_tile_request_dialog_not_add" msgid="4168716573114067296">"Non aggiungerlo"</string>
<string name="qs_user_switch_dialog_title" msgid="3045189293587781366">"Seleziona utente"</string>
<plurals name="fgs_manager_footer_label" formatted="false" msgid="9091110396713032871">
- <item quantity="one"><xliff:g id="COUNT_1">%s</xliff:g> app attiva</item>
<item quantity="other"><xliff:g id="COUNT_1">%s</xliff:g> app attive</item>
+ <item quantity="one"><xliff:g id="COUNT_0">%s</xliff:g> app attiva</item>
</plurals>
<string name="fgs_dot_content_description" msgid="2865071539464777240">"Nuove informazioni"</string>
<string name="fgs_manager_dialog_title" msgid="5879184257257718677">"App attive"</string>
@@ -916,7 +913,6 @@
<string name="dream_overlay_status_bar_wifi_off" msgid="4497069245055003582">"Wi‑Fi non disponibile"</string>
<string name="dream_overlay_status_bar_priority_mode" msgid="5428462123314728739">"Modalità Priorità"</string>
<string name="dream_overlay_status_bar_alarm_set" msgid="566707328356590886">"Sveglia impostata"</string>
- <string name="dream_overlay_status_bar_assistant_guest_mode_enabled" msgid="3715897096012469615">"Modalità Ospite dell\'assistente attiva"</string>
<string name="dream_overlay_status_bar_camera_mic_off" msgid="3199425257833773569">"Fotocamera e microfono non attivi"</string>
- <string name="dream_overlay_status_bar_notification_indicator" msgid="8091389255691081711">"{count,plural, =1{# notifica}one{# notifica}other{# notifiche}}"</string>
+ <string name="dream_overlay_status_bar_notification_indicator" msgid="8091389255691081711">"{count,plural, =1{# notifica}other{# notifiche}}"</string>
</resources>
diff --git a/packages/SystemUI/res/values-iw/strings.xml b/packages/SystemUI/res/values-iw/strings.xml
index f88605a..7dcde9cf 100644
--- a/packages/SystemUI/res/values-iw/strings.xml
+++ b/packages/SystemUI/res/values-iw/strings.xml
@@ -20,19 +20,17 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_label" msgid="4811759950673118541">"ממשק משתמש של המערכת"</string>
- <!-- no translation found for battery_low_title (5319680173344341779) -->
- <skip />
- <!-- no translation found for battery_low_description (3282977755476423966) -->
- <skip />
- <!-- no translation found for battery_low_intro (5148725009653088790) -->
- <skip />
+ <string name="battery_low_title" msgid="5319680173344341779">"להפעיל את התכונה \'חיסכון בסוללה\'?"</string>
+ <string name="battery_low_description" msgid="3282977755476423966">"אחוז הטעינה של הסוללה: <xliff:g id="PERCENTAGE">%s</xliff:g>. התכונה \'חיסכון בסוללה\' מפעילה עיצוב כהה, מגבילה את הפעילת ברקע ומשהה את ההתראות."</string>
+ <string name="battery_low_intro" msgid="5148725009653088790">"התכונה \'חיסכון בסוללה\' מפעילה עיצוב כהה, מגבילה את הפעילת ברקע ומשהה את ההתראות."</string>
<string name="battery_low_percent_format" msgid="4276661262843170964">"נותרו <xliff:g id="PERCENTAGE">%s</xliff:g>"</string>
<string name="invalid_charger_title" msgid="938685362320735167">"לא ניתן לטעון באמצעות USB"</string>
<string name="invalid_charger_text" msgid="2339310107232691577">"שימוש במטען שסופק עם המכשיר"</string>
<string name="battery_saver_confirmation_title" msgid="1234998463717398453">"להפעיל את תכונת החיסכון בסוללה?"</string>
<string name="battery_saver_confirmation_title_generic" msgid="2299231884234959849">"מידע על מצב \'חיסכון בסוללה\'"</string>
<string name="battery_saver_confirmation_ok" msgid="5042136476802816494">"הפעלה"</string>
- <string name="battery_saver_start_action" msgid="4553256017945469937">"הפעלת תכונת החיסכון בסוללה"</string>
+ <string name="battery_saver_start_action" msgid="8353766979886287140">"הפעלה"</string>
+ <string name="battery_saver_dismiss_action" msgid="7199342621040014738">"לא תודה"</string>
<string name="status_bar_settings_auto_rotation" msgid="8329080442278431708">"סיבוב אוטומטי של המסך"</string>
<string name="usb_device_permission_prompt" msgid="4414719028369181772">"לתת לאפליקציה <xliff:g id="APPLICATION">%1$s</xliff:g> גישה אל <xliff:g id="USB_DEVICE">%2$s</xliff:g>?"</string>
<string name="usb_device_permission_prompt_warn" msgid="2309129784984063656">"האם לאפשר לאפליקציה <xliff:g id="APPLICATION">%1$s</xliff:g> גישה אל <xliff:g id="USB_DEVICE">%2$s</xliff:g>?\nאפליקציה זו לא קיבלה הרשאה להקליט אך יכולה לתעד אודיו באמצעות מכשיר USB זה."</string>
@@ -133,8 +131,7 @@
<string name="biometric_dialog_face_icon_description_authenticated" msgid="2242167416140740920">"זיהוי הפנים בוצע"</string>
<string name="biometric_dialog_face_icon_description_confirmed" msgid="7918067993953940778">"יש אישור"</string>
<string name="biometric_dialog_tap_confirm" msgid="9166350738859143358">"יש להקיש על \'אישור\' לסיום התהליך"</string>
- <!-- no translation found for biometric_dialog_tap_confirm_with_face (1597899891472340950) -->
- <skip />
+ <string name="biometric_dialog_tap_confirm_with_face" msgid="1597899891472340950">"הנעילה בוטלה עם זיהוי הפנים שלך. יש ללחוץ כדי להמשיך."</string>
<string name="biometric_dialog_authenticated" msgid="7337147327545272484">"מאומת"</string>
<string name="biometric_dialog_use_pin" msgid="8385294115283000709">"שימוש בקוד אימות"</string>
<string name="biometric_dialog_use_pattern" msgid="2315593393167211194">"שימוש בקו ביטול נעילה"</string>
@@ -468,8 +465,8 @@
<string name="wallet_secondary_label_device_locked" msgid="5175862019125370506">"יש לבטל את הנעילה כדי להשתמש"</string>
<string name="wallet_error_generic" msgid="257704570182963611">"הייתה בעיה בקבלת הכרטיסים שלך. כדאי לנסות שוב מאוחר יותר"</string>
<string name="wallet_lockscreen_settings_label" msgid="3539105300870383570">"הגדרות מסך הנעילה"</string>
- <string name="qr_code_scanner_title" msgid="5660820608548306581">"קוד QR"</string>
- <string name="qr_code_scanner_description" msgid="7937603775306661863">"צריך להקיש כדי לסרוק"</string>
+ <!-- no translation found for qr_code_scanner_title (5290201053875420785) -->
+ <skip />
<string name="status_bar_work" msgid="5238641949837091056">"פרופיל עבודה"</string>
<string name="status_bar_airplane" msgid="4848702508684541009">"מצב טיסה"</string>
<string name="zen_alarm_warning" msgid="7844303238486849503">"לא ניתן יהיה לשמוע את ההתראה הבאה שלך <xliff:g id="WHEN">%1$s</xliff:g>"</string>
@@ -839,6 +836,7 @@
<string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"התאמה של מכשיר חדש"</string>
<string name="media_output_dialog_launch_app_text" msgid="1527413319632586259">"כדי להעביר (cast) את הסשן הזה, צריך לפתוח את האפליקציה."</string>
<string name="media_output_dialog_unknown_launch_app_name" msgid="1084899329829371336">"אפליקציה לא ידועה"</string>
+ <string name="media_output_dialog_button_stop_casting" msgid="6581379537930199189">"עצירת ההעברה (casting)"</string>
<string name="build_number_clip_data_label" msgid="3623176728412560914">"מספר Build"</string>
<string name="build_number_copy_toast" msgid="877720921605503046">"מספר ה-Build הועתק ללוח."</string>
<string name="basic_status" msgid="2315371112182658176">"פתיחת שיחה"</string>
@@ -930,8 +928,6 @@
<string name="dream_overlay_status_bar_wifi_off" msgid="4497069245055003582">"Wi‑Fi לא זמין"</string>
<string name="dream_overlay_status_bar_priority_mode" msgid="5428462123314728739">"מצב עדיפות"</string>
<string name="dream_overlay_status_bar_alarm_set" msgid="566707328356590886">"ההתראה מוגדרת"</string>
- <string name="dream_overlay_status_bar_assistant_guest_mode_enabled" msgid="3715897096012469615">"מצב אורח ב‑Assistant מופעל"</string>
<string name="dream_overlay_status_bar_camera_mic_off" msgid="3199425257833773569">"המצלמה והמיקרופון כבויים"</string>
- <!-- no translation found for dream_overlay_status_bar_notification_indicator (8091389255691081711) -->
- <skip />
+ <string name="dream_overlay_status_bar_notification_indicator" msgid="8091389255691081711">"{count,plural, =1{התראה אחת}two{# התראות}many{# התראות}other{# התראות}}"</string>
</resources>
diff --git a/packages/SystemUI/res/values-ja/strings.xml b/packages/SystemUI/res/values-ja/strings.xml
index b946344..956826b 100644
--- a/packages/SystemUI/res/values-ja/strings.xml
+++ b/packages/SystemUI/res/values-ja/strings.xml
@@ -20,19 +20,17 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_label" msgid="4811759950673118541">"システム UI"</string>
- <!-- no translation found for battery_low_title (5319680173344341779) -->
- <skip />
- <!-- no translation found for battery_low_description (3282977755476423966) -->
- <skip />
- <!-- no translation found for battery_low_intro (5148725009653088790) -->
- <skip />
+ <string name="battery_low_title" msgid="5319680173344341779">"バッテリー セーバーを ON にしますか?"</string>
+ <string name="battery_low_description" msgid="3282977755476423966">"バッテリー残量は <xliff:g id="PERCENTAGE">%s</xliff:g> です。バッテリー セーバーを有効にすると、ダークモードが ON になります。また、バックグラウンド アクティビティが制限され、通知が届くのが遅くなります。"</string>
+ <string name="battery_low_intro" msgid="5148725009653088790">"バッテリー セーバーを有効にすると、ダークモードが ON になります。また、バックグラウンド アクティビティが制限され、通知が届くのが遅くなります。"</string>
<string name="battery_low_percent_format" msgid="4276661262843170964">"残量が<xliff:g id="PERCENTAGE">%s</xliff:g>です"</string>
<string name="invalid_charger_title" msgid="938685362320735167">"USB 経由では充電できません"</string>
<string name="invalid_charger_text" msgid="2339310107232691577">"デバイスに付属の充電器を使用してください"</string>
<string name="battery_saver_confirmation_title" msgid="1234998463717398453">"バッテリー セーバーを ON にしますか?"</string>
<string name="battery_saver_confirmation_title_generic" msgid="2299231884234959849">"バッテリー セーバーについて"</string>
<string name="battery_saver_confirmation_ok" msgid="5042136476802816494">"ONにする"</string>
- <string name="battery_saver_start_action" msgid="4553256017945469937">"バッテリー セーバーを ON"</string>
+ <string name="battery_saver_start_action" msgid="8353766979886287140">"ON にする"</string>
+ <string name="battery_saver_dismiss_action" msgid="7199342621040014738">"いいえ"</string>
<string name="status_bar_settings_auto_rotation" msgid="8329080442278431708">"自動回転画面"</string>
<string name="usb_device_permission_prompt" msgid="4414719028369181772">"<xliff:g id="APPLICATION">%1$s</xliff:g> に <xliff:g id="USB_DEVICE">%2$s</xliff:g> へのアクセスを許可しますか?"</string>
<string name="usb_device_permission_prompt_warn" msgid="2309129784984063656">"<xliff:g id="APPLICATION">%1$s</xliff:g> に <xliff:g id="USB_DEVICE">%2$s</xliff:g>へのアクセスを許可しますか?\nこのアプリに録音権限は付与されていませんが、アクセスを許可すると、この USB デバイスから音声を収集できるようになります。"</string>
@@ -133,8 +131,7 @@
<string name="biometric_dialog_face_icon_description_authenticated" msgid="2242167416140740920">"顔を認証しました"</string>
<string name="biometric_dialog_face_icon_description_confirmed" msgid="7918067993953940778">"確認しました"</string>
<string name="biometric_dialog_tap_confirm" msgid="9166350738859143358">"完了するには [確認] をタップしてください"</string>
- <!-- no translation found for biometric_dialog_tap_confirm_with_face (1597899891472340950) -->
- <skip />
+ <string name="biometric_dialog_tap_confirm_with_face" msgid="1597899891472340950">"顔認識でロックを解除しました。押して続行してください。"</string>
<string name="biometric_dialog_authenticated" msgid="7337147327545272484">"認証済み"</string>
<string name="biometric_dialog_use_pin" msgid="8385294115283000709">"PIN を使用"</string>
<string name="biometric_dialog_use_pattern" msgid="2315593393167211194">"パターンを使用"</string>
@@ -462,8 +459,7 @@
<string name="wallet_secondary_label_device_locked" msgid="5175862019125370506">"ロックを解除して使用"</string>
<string name="wallet_error_generic" msgid="257704570182963611">"カードの取得中に問題が発生しました。しばらくしてからもう一度お試しください"</string>
<string name="wallet_lockscreen_settings_label" msgid="3539105300870383570">"ロック画面の設定"</string>
- <string name="qr_code_scanner_title" msgid="5660820608548306581">"QR コード"</string>
- <string name="qr_code_scanner_description" msgid="7937603775306661863">"タップしてスキャンします"</string>
+ <string name="qr_code_scanner_title" msgid="5290201053875420785">"QR コードのスキャン"</string>
<string name="status_bar_work" msgid="5238641949837091056">"仕事用プロファイル"</string>
<string name="status_bar_airplane" msgid="4848702508684541009">"機内モード"</string>
<string name="zen_alarm_warning" msgid="7844303238486849503">"次回のアラーム(<xliff:g id="WHEN">%1$s</xliff:g>)は鳴りません"</string>
@@ -827,6 +823,7 @@
<string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"新しいデバイスとのペア設定"</string>
<string name="media_output_dialog_launch_app_text" msgid="1527413319632586259">"このセッションをキャストするには、アプリを開いてください。"</string>
<string name="media_output_dialog_unknown_launch_app_name" msgid="1084899329829371336">"不明なアプリ"</string>
+ <string name="media_output_dialog_button_stop_casting" msgid="6581379537930199189">"キャストを停止"</string>
<string name="build_number_clip_data_label" msgid="3623176728412560914">"ビルド番号"</string>
<string name="build_number_copy_toast" msgid="877720921605503046">"ビルド番号をクリップボードにコピーしました。"</string>
<string name="basic_status" msgid="2315371112182658176">"空の会話"</string>
@@ -916,7 +913,6 @@
<string name="dream_overlay_status_bar_wifi_off" msgid="4497069245055003582">"Wi-Fi を利用できません"</string>
<string name="dream_overlay_status_bar_priority_mode" msgid="5428462123314728739">"優先順位モード"</string>
<string name="dream_overlay_status_bar_alarm_set" msgid="566707328356590886">"アラームを設定しました"</string>
- <string name="dream_overlay_status_bar_assistant_guest_mode_enabled" msgid="3715897096012469615">"アシスタント ゲストモードを有効にしました"</string>
<string name="dream_overlay_status_bar_camera_mic_off" msgid="3199425257833773569">"カメラとマイクが OFF です"</string>
<string name="dream_overlay_status_bar_notification_indicator" msgid="8091389255691081711">"{count,plural, =1{# 件の通知}other{# 件の通知}}"</string>
</resources>
diff --git a/packages/SystemUI/res/values-ka/strings.xml b/packages/SystemUI/res/values-ka/strings.xml
index 31d7606..7ecdfd9 100644
--- a/packages/SystemUI/res/values-ka/strings.xml
+++ b/packages/SystemUI/res/values-ka/strings.xml
@@ -20,19 +20,17 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_label" msgid="4811759950673118541">"სისტემის UI"</string>
- <!-- no translation found for battery_low_title (5319680173344341779) -->
- <skip />
- <!-- no translation found for battery_low_description (3282977755476423966) -->
- <skip />
- <!-- no translation found for battery_low_intro (5148725009653088790) -->
- <skip />
+ <string name="battery_low_title" msgid="5319680173344341779">"გსურთ ბატარეის დამზოგის ჩართვა?"</string>
+ <string name="battery_low_description" msgid="3282977755476423966">"თქვენი ბატარეა დატენილია <xliff:g id="PERCENTAGE">%s</xliff:g>-ზე. ბატარეის დამზოგი ჩართავს მუქ თემას, შეზღუდავს აქტივობას ფონურ რეჟიმში და შეტყობინებების მიღება შეფერხდება."</string>
+ <string name="battery_low_intro" msgid="5148725009653088790">"ბატარეის დამზოგი ჩართავს მუქ თემას, შეზღუდავს აქტივობას ფონურ რეჟიმში და შეტყობინებების მიღება შეფერხდება."</string>
<string name="battery_low_percent_format" msgid="4276661262843170964">"დარჩენილია <xliff:g id="PERCENTAGE">%s</xliff:g>"</string>
<string name="invalid_charger_title" msgid="938685362320735167">"USB-თ დატენვა ვერ ხერხდება"</string>
<string name="invalid_charger_text" msgid="2339310107232691577">"გამოიყენეთ დამტენი, რომელიც თქვენს მოწყობილობას მოჰყვა"</string>
<string name="battery_saver_confirmation_title" msgid="1234998463717398453">"გსურთ ბატარეის დამზოგის ჩართვა?"</string>
<string name="battery_saver_confirmation_title_generic" msgid="2299231884234959849">"ბატარეის დამზოგის შესახებ"</string>
<string name="battery_saver_confirmation_ok" msgid="5042136476802816494">"ჩართვა"</string>
- <string name="battery_saver_start_action" msgid="4553256017945469937">"ბატარეის დამზოგის ჩართვა"</string>
+ <string name="battery_saver_start_action" msgid="8353766979886287140">"ჩართვა"</string>
+ <string name="battery_saver_dismiss_action" msgid="7199342621040014738">"არა, გმადლობთ"</string>
<string name="status_bar_settings_auto_rotation" msgid="8329080442278431708">"ეკრანის ავტოროტაცია"</string>
<string name="usb_device_permission_prompt" msgid="4414719028369181772">"მიეცეს <xliff:g id="APPLICATION">%1$s</xliff:g>-ს <xliff:g id="USB_DEVICE">%2$s</xliff:g>-ზე წვდომის უფლება?"</string>
<string name="usb_device_permission_prompt_warn" msgid="2309129784984063656">"დართავთ <xliff:g id="APPLICATION">%1$s</xliff:g>-ს <xliff:g id="USB_DEVICE">%2$s</xliff:g>-ზე წვდომის ნებას?\nამ აპს არ აქვს მინიჭებული ჩაწერის ნებართვა, მაგრამ შეუძლია ჩაიწეროს აუდიო ამ USB მოწყობილობის მეშვეობით."</string>
@@ -133,8 +131,7 @@
<string name="biometric_dialog_face_icon_description_authenticated" msgid="2242167416140740920">"სახის ამოცნობილია"</string>
<string name="biometric_dialog_face_icon_description_confirmed" msgid="7918067993953940778">"დადასტურებული"</string>
<string name="biometric_dialog_tap_confirm" msgid="9166350738859143358">"დასასრულებლად შეეხეთ „დადასტურებას“"</string>
- <!-- no translation found for biometric_dialog_tap_confirm_with_face (1597899891472340950) -->
- <skip />
+ <string name="biometric_dialog_tap_confirm_with_face" msgid="1597899891472340950">"განბლოკილია თქვენი სახით. დააჭირეთ გასაგრძელებლად."</string>
<string name="biometric_dialog_authenticated" msgid="7337147327545272484">"ავტორიზებულია"</string>
<string name="biometric_dialog_use_pin" msgid="8385294115283000709">"PIN-კოდის გამოყენება"</string>
<string name="biometric_dialog_use_pattern" msgid="2315593393167211194">"ნიმუშის გამოყენება"</string>
@@ -462,8 +459,8 @@
<string name="wallet_secondary_label_device_locked" msgid="5175862019125370506">"გამოსაყენებლად განბლოკვა"</string>
<string name="wallet_error_generic" msgid="257704570182963611">"თქვენი ბარათების მიღებისას პრობლემა წარმოიშვა. ცადეთ ხელახლა მოგვიანებით"</string>
<string name="wallet_lockscreen_settings_label" msgid="3539105300870383570">"ჩაკეტილი ეკრანის პარამეტრები"</string>
- <string name="qr_code_scanner_title" msgid="5660820608548306581">"QR კოდი"</string>
- <string name="qr_code_scanner_description" msgid="7937603775306661863">"შეეხეთ დასასკანირებლად"</string>
+ <!-- no translation found for qr_code_scanner_title (5290201053875420785) -->
+ <skip />
<string name="status_bar_work" msgid="5238641949837091056">"სამსახურის პროფილი"</string>
<string name="status_bar_airplane" msgid="4848702508684541009">"თვითმფრინავის რეჟიმი"</string>
<string name="zen_alarm_warning" msgid="7844303238486849503">"ვერ გაიგონებთ მომდევნო მაღვიძარას <xliff:g id="WHEN">%1$s</xliff:g>-ზე"</string>
@@ -827,6 +824,7 @@
<string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"ახალი მოწყობილობის დაწყვილება"</string>
<string name="media_output_dialog_launch_app_text" msgid="1527413319632586259">"ამ სესიის ტრანსლირებისთვის გახსენით აპი."</string>
<string name="media_output_dialog_unknown_launch_app_name" msgid="1084899329829371336">"უცნობი აპი"</string>
+ <string name="media_output_dialog_button_stop_casting" msgid="6581379537930199189">"ტრანსლირების შეწყვეტა"</string>
<string name="build_number_clip_data_label" msgid="3623176728412560914">"ანაწყობის ნომერი"</string>
<string name="build_number_copy_toast" msgid="877720921605503046">"ანაწყობის ნომერი დაკოპირებულია გაცვლის ბუფერში."</string>
<string name="basic_status" msgid="2315371112182658176">"მიმოწერის გახსნა"</string>
@@ -916,7 +914,6 @@
<string name="dream_overlay_status_bar_wifi_off" msgid="4497069245055003582">"Wi‑Fi მიუწვდომელია"</string>
<string name="dream_overlay_status_bar_priority_mode" msgid="5428462123314728739">"პრიორიტეტული რეჟიმი"</string>
<string name="dream_overlay_status_bar_alarm_set" msgid="566707328356590886">"მაღვიძარა დაყენებულია"</string>
- <string name="dream_overlay_status_bar_assistant_guest_mode_enabled" msgid="3715897096012469615">"ასისტენტის სტუმრის რეჟიმი ჩართულია"</string>
<string name="dream_overlay_status_bar_camera_mic_off" msgid="3199425257833773569">"კამერა და მიკროფონი გამორთულია"</string>
<string name="dream_overlay_status_bar_notification_indicator" msgid="8091389255691081711">"{count,plural, =1{# შეტყობინება}other{# შეტყობინება}}"</string>
</resources>
diff --git a/packages/SystemUI/res/values-kk/strings.xml b/packages/SystemUI/res/values-kk/strings.xml
index c8abf95..85283de 100644
--- a/packages/SystemUI/res/values-kk/strings.xml
+++ b/packages/SystemUI/res/values-kk/strings.xml
@@ -20,19 +20,17 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_label" msgid="4811759950673118541">"Жүйе интерфейсі"</string>
- <!-- no translation found for battery_low_title (5319680173344341779) -->
- <skip />
- <!-- no translation found for battery_low_description (3282977755476423966) -->
- <skip />
- <!-- no translation found for battery_low_intro (5148725009653088790) -->
- <skip />
+ <string name="battery_low_title" msgid="5319680173344341779">"Батареяны үнемдеу режимі қосылсын ба?"</string>
+ <string name="battery_low_description" msgid="3282977755476423966">"<xliff:g id="PERCENTAGE">%s</xliff:g> заряд қалды. Батареяны үнемдеу режимі қараңғы тақырыпты іске қосады, фондық әрекеттерге шектеу қояды және хабарландыруларды кідіртеді."</string>
+ <string name="battery_low_intro" msgid="5148725009653088790">"Батареяны үнемдеу режимі қараңғы тақырыпты іске қосады, фондық әрекеттерге шектеу қояды және хабарландыруларды кідіртеді."</string>
<string name="battery_low_percent_format" msgid="4276661262843170964">"<xliff:g id="PERCENTAGE">%s</xliff:g> қалды"</string>
<string name="invalid_charger_title" msgid="938685362320735167">"USB арқылы зарядтау мүмкін емес"</string>
<string name="invalid_charger_text" msgid="2339310107232691577">"Құрылғымен бірге берілген зарядтау құралын пайдаланыңыз"</string>
<string name="battery_saver_confirmation_title" msgid="1234998463717398453">"Батареяны үнемдеу режимін қосу керек пе?"</string>
<string name="battery_saver_confirmation_title_generic" msgid="2299231884234959849">"Батареяны үнемдеу режимі туралы ақпарат"</string>
<string name="battery_saver_confirmation_ok" msgid="5042136476802816494">"Қосу"</string>
- <string name="battery_saver_start_action" msgid="4553256017945469937">"Батареяны үнемдеу режимін қосу"</string>
+ <string name="battery_saver_start_action" msgid="8353766979886287140">"Қосу"</string>
+ <string name="battery_saver_dismiss_action" msgid="7199342621040014738">"Жоқ, рақмет"</string>
<string name="status_bar_settings_auto_rotation" msgid="8329080442278431708">"Авто айналатын экран"</string>
<string name="usb_device_permission_prompt" msgid="4414719028369181772">"<xliff:g id="APPLICATION">%1$s</xliff:g> қолданбасына <xliff:g id="USB_DEVICE">%2$s</xliff:g> құрылғысына кіруге рұқсат берілсін бе?"</string>
<string name="usb_device_permission_prompt_warn" msgid="2309129784984063656">"<xliff:g id="APPLICATION">%1$s</xliff:g> қолданбасына <xliff:g id="USB_DEVICE">%2$s</xliff:g> құрылғысын пайдалануға рұқсат етілсін бе?\nҚолданбаның жазу рұқсаты жоқ, бірақ осы USB құрылғысы арқылы аудио жаза алады."</string>
@@ -133,8 +131,7 @@
<string name="biometric_dialog_face_icon_description_authenticated" msgid="2242167416140740920">"Бет танылды."</string>
<string name="biometric_dialog_face_icon_description_confirmed" msgid="7918067993953940778">"Расталды"</string>
<string name="biometric_dialog_tap_confirm" msgid="9166350738859143358">"Аяқтау үшін \"Растау\" түймесін түртіңіз."</string>
- <!-- no translation found for biometric_dialog_tap_confirm_with_face (1597899891472340950) -->
- <skip />
+ <string name="biometric_dialog_tap_confirm_with_face" msgid="1597899891472340950">"Құлып бетіңіз арқылы ашылды. Жалғастыру үшін басыңыз."</string>
<string name="biometric_dialog_authenticated" msgid="7337147327545272484">"Аутентификацияланған"</string>
<string name="biometric_dialog_use_pin" msgid="8385294115283000709">"PIN кодын пайдалану"</string>
<string name="biometric_dialog_use_pattern" msgid="2315593393167211194">"Өрнекті пайдалану"</string>
@@ -462,8 +459,8 @@
<string name="wallet_secondary_label_device_locked" msgid="5175862019125370506">"Пайдалану үшін құлыпты ашу"</string>
<string name="wallet_error_generic" msgid="257704570182963611">"Карталарыңыз алынбады, кейінірек қайталап көріңіз."</string>
<string name="wallet_lockscreen_settings_label" msgid="3539105300870383570">"Экран құлпының параметрлері"</string>
- <string name="qr_code_scanner_title" msgid="5660820608548306581">"QR коды"</string>
- <string name="qr_code_scanner_description" msgid="7937603775306661863">"Сканерлеу үшін түртіңіз."</string>
+ <!-- no translation found for qr_code_scanner_title (5290201053875420785) -->
+ <skip />
<string name="status_bar_work" msgid="5238641949837091056">"Жұмыс профилі"</string>
<string name="status_bar_airplane" msgid="4848702508684541009">"Ұшақ режимі"</string>
<string name="zen_alarm_warning" msgid="7844303238486849503">"Келесі <xliff:g id="WHEN">%1$s</xliff:g> дабылыңызды есітпейсіз"</string>
@@ -827,6 +824,7 @@
<string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"Жаңа құрылғымен жұптау"</string>
<string name="media_output_dialog_launch_app_text" msgid="1527413319632586259">"Бұл сеансты трансляциялау үшін қолданбаны ашыңыз."</string>
<string name="media_output_dialog_unknown_launch_app_name" msgid="1084899329829371336">"Белгісіз қолданба"</string>
+ <string name="media_output_dialog_button_stop_casting" msgid="6581379537930199189">"Трансляцияны тоқтату"</string>
<string name="build_number_clip_data_label" msgid="3623176728412560914">"Құрама нөмірі"</string>
<string name="build_number_copy_toast" msgid="877720921605503046">"Құрама нөмірі буферге көшірілді."</string>
<string name="basic_status" msgid="2315371112182658176">"Ашық әңгіме"</string>
@@ -916,8 +914,6 @@
<string name="dream_overlay_status_bar_wifi_off" msgid="4497069245055003582">"Wi‑Fi қолжетімсіз"</string>
<string name="dream_overlay_status_bar_priority_mode" msgid="5428462123314728739">"Басымдық режимі"</string>
<string name="dream_overlay_status_bar_alarm_set" msgid="566707328356590886">"Оятқыш орнатылды"</string>
- <string name="dream_overlay_status_bar_assistant_guest_mode_enabled" msgid="3715897096012469615">"Assistant қонақ режимі қосылды"</string>
<string name="dream_overlay_status_bar_camera_mic_off" msgid="3199425257833773569">"Камера мен микрофон өшірулі"</string>
- <!-- no translation found for dream_overlay_status_bar_notification_indicator (8091389255691081711) -->
- <skip />
+ <string name="dream_overlay_status_bar_notification_indicator" msgid="8091389255691081711">"{count,plural, =1{# хабарландыру}other{# хабарландыру}}"</string>
</resources>
diff --git a/packages/SystemUI/res/values-km/strings.xml b/packages/SystemUI/res/values-km/strings.xml
index 78e6c84..9e527e4 100644
--- a/packages/SystemUI/res/values-km/strings.xml
+++ b/packages/SystemUI/res/values-km/strings.xml
@@ -20,19 +20,17 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_label" msgid="4811759950673118541">"UI ប្រព័ន្ធ"</string>
- <!-- no translation found for battery_low_title (5319680173344341779) -->
- <skip />
- <!-- no translation found for battery_low_description (3282977755476423966) -->
- <skip />
- <!-- no translation found for battery_low_intro (5148725009653088790) -->
- <skip />
+ <string name="battery_low_title" msgid="5319680173344341779">"បើកមុខងារសន្សំថ្មឬ?"</string>
+ <string name="battery_low_description" msgid="3282977755476423966">"អ្នកនៅសល់ថ្ម <xliff:g id="PERCENTAGE">%s</xliff:g> ទៀត។ មុខងារសន្សំថ្មបើករចនាប័ទ្មងងឹត ដាក់កំហិតសកម្មភាពនៅផ្ទៃខាងក្រោយ និងពន្យារពេលជូនដំណឹង។"</string>
+ <string name="battery_low_intro" msgid="5148725009653088790">"មុខងារសន្សំថ្មបើករចនាប័ទ្មងងឹត ដាក់កំហិតសកម្មភាពនៅផ្ទៃខាងក្រោយ និងពន្យារពេលជូនដំណឹង។"</string>
<string name="battery_low_percent_format" msgid="4276661262843170964">"នៅសល់ <xliff:g id="PERCENTAGE">%s</xliff:g>"</string>
<string name="invalid_charger_title" msgid="938685362320735167">"មិនអាចសាកតាម USB បានទេ"</string>
<string name="invalid_charger_text" msgid="2339310107232691577">"សូមប្រើឆ្នាំងសាកដែលភ្ជាប់មកជាមួយឧបករណ៍របស់អ្នក"</string>
<string name="battery_saver_confirmation_title" msgid="1234998463717398453">"បើកមុខងារសន្សំថ្ម?"</string>
<string name="battery_saver_confirmation_title_generic" msgid="2299231884234959849">"អំពីមុខងារសន្សំថ្ម"</string>
<string name="battery_saver_confirmation_ok" msgid="5042136476802816494">"បើក"</string>
- <string name="battery_saver_start_action" msgid="4553256017945469937">"បើកមុខងារសន្សំថ្ម"</string>
+ <string name="battery_saver_start_action" msgid="8353766979886287140">"បើក"</string>
+ <string name="battery_saver_dismiss_action" msgid="7199342621040014738">"ទេ អរគុណ"</string>
<string name="status_bar_settings_auto_rotation" msgid="8329080442278431708">"បង្វិលអេក្រង់ស្វ័យប្រវត្តិ"</string>
<string name="usb_device_permission_prompt" msgid="4414719028369181772">"អនុញ្ញាត <xliff:g id="APPLICATION">%1$s</xliff:g> ឱ្យចូលប្រើ <xliff:g id="USB_DEVICE">%2$s</xliff:g> មែនទេ?"</string>
<string name="usb_device_permission_prompt_warn" msgid="2309129784984063656">"អនុញ្ញាតឱ្យ <xliff:g id="APPLICATION">%1$s</xliff:g> ចូលប្រើ <xliff:g id="USB_DEVICE">%2$s</xliff:g>?\nកម្មវិធីនេះមិនទាន់បានទទួលសិទ្ធិថតសំឡេងនៅឡើយទេ ប៉ុន្តែអាចថតសំឡេងតាមរយៈឧបករណ៍ USB នេះបាន។"</string>
@@ -133,8 +131,7 @@
<string name="biometric_dialog_face_icon_description_authenticated" msgid="2242167416140740920">"បានផ្ទៀងផ្ទាត់មុខ"</string>
<string name="biometric_dialog_face_icon_description_confirmed" msgid="7918067993953940778">"បានបញ្ជាក់"</string>
<string name="biometric_dialog_tap_confirm" msgid="9166350738859143358">"ចុច \"បញ្ជាក់\" ដើម្បីបញ្ចប់"</string>
- <!-- no translation found for biometric_dialog_tap_confirm_with_face (1597899891472340950) -->
- <skip />
+ <string name="biometric_dialog_tap_confirm_with_face" msgid="1597899891472340950">"បានដោះសោដោយប្រើមុខរបស់អ្នក។ ចុច ដើម្បីបន្ត។"</string>
<string name="biometric_dialog_authenticated" msgid="7337147327545272484">"បានផ្ទៀងផ្ទាត់"</string>
<string name="biometric_dialog_use_pin" msgid="8385294115283000709">"ប្រើកូដ PIN"</string>
<string name="biometric_dialog_use_pattern" msgid="2315593393167211194">"ប្រើលំនាំ"</string>
@@ -462,8 +459,8 @@
<string name="wallet_secondary_label_device_locked" msgid="5175862019125370506">"ដោះសោដើម្បីប្រើប្រាស់"</string>
<string name="wallet_error_generic" msgid="257704570182963611">"មានបញ្ហាក្នុងការទាញយកកាតរបស់អ្នក សូមព្យាយាមម្ដងទៀតនៅពេលក្រោយ"</string>
<string name="wallet_lockscreen_settings_label" msgid="3539105300870383570">"ការកំណត់អេក្រង់ចាក់សោ"</string>
- <string name="qr_code_scanner_title" msgid="5660820608548306581">"កូដ QR"</string>
- <string name="qr_code_scanner_description" msgid="7937603775306661863">"ចុចដើម្បីស្កេន"</string>
+ <!-- no translation found for qr_code_scanner_title (5290201053875420785) -->
+ <skip />
<string name="status_bar_work" msgid="5238641949837091056">"ប្រវត្តិរូបការងារ"</string>
<string name="status_bar_airplane" msgid="4848702508684541009">"ពេលជិះយន្តហោះ"</string>
<string name="zen_alarm_warning" msgid="7844303238486849503">"អ្នកនឹងមិនលឺម៉ោងរោទ៍ <xliff:g id="WHEN">%1$s</xliff:g> បន្ទាប់របស់អ្នកទេ"</string>
@@ -827,6 +824,7 @@
<string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"ផ្គូផ្គងឧបករណ៍ថ្មី"</string>
<string name="media_output_dialog_launch_app_text" msgid="1527413319632586259">"ដើម្បីភ្ជាប់វគ្គនេះ សូមបើកកម្មវិធី។"</string>
<string name="media_output_dialog_unknown_launch_app_name" msgid="1084899329829371336">"កម្មវិធីដែលមិនស្គាល់"</string>
+ <string name="media_output_dialog_button_stop_casting" msgid="6581379537930199189">"បញ្ឈប់ការភ្ជាប់"</string>
<string name="build_number_clip_data_label" msgid="3623176728412560914">"លេខកំណែបង្កើត"</string>
<string name="build_number_copy_toast" msgid="877720921605503046">"បានចម្លងលេខកំណែបង្កើតទៅឃ្លីបបត។"</string>
<string name="basic_status" msgid="2315371112182658176">"បើកការសន្ទនា"</string>
@@ -916,7 +914,6 @@
<string name="dream_overlay_status_bar_wifi_off" msgid="4497069245055003582">"Wi‑Fi ត្រូវបានបិទ"</string>
<string name="dream_overlay_status_bar_priority_mode" msgid="5428462123314728739">"មុខងារអាទិភាព"</string>
<string name="dream_overlay_status_bar_alarm_set" msgid="566707328356590886">"រូបកំណត់ម៉ោងរោទ៍"</string>
- <string name="dream_overlay_status_bar_assistant_guest_mode_enabled" msgid="3715897096012469615">"បានបើកមុខងារភ្ញៀវរបស់ Assistant"</string>
<string name="dream_overlay_status_bar_camera_mic_off" msgid="3199425257833773569">"កាមេរ៉ា និងមីក្រូហ្វូនត្រូវបានបិទ"</string>
<string name="dream_overlay_status_bar_notification_indicator" msgid="8091389255691081711">"{count,plural, =1{ការជូនដំណឹង #}other{ការជូនដំណឹង #}}"</string>
</resources>
diff --git a/packages/SystemUI/res/values-kn/strings.xml b/packages/SystemUI/res/values-kn/strings.xml
index e10f5d3..ce0ca0e 100644
--- a/packages/SystemUI/res/values-kn/strings.xml
+++ b/packages/SystemUI/res/values-kn/strings.xml
@@ -20,19 +20,17 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_label" msgid="4811759950673118541">"ಸಿಸ್ಟಂ UI"</string>
- <!-- no translation found for battery_low_title (5319680173344341779) -->
- <skip />
- <!-- no translation found for battery_low_description (3282977755476423966) -->
- <skip />
- <!-- no translation found for battery_low_intro (5148725009653088790) -->
- <skip />
+ <string name="battery_low_title" msgid="5319680173344341779">"ಬ್ಯಾಟರಿ ಸೇವರ್ ಅನ್ನು ಆನ್ ಮಾಡಬೇಕೇ?"</string>
+ <string name="battery_low_description" msgid="3282977755476423966">"ನಿಮ್ಮ ಬಳಿ <xliff:g id="PERCENTAGE">%s</xliff:g> ಬ್ಯಾಟರಿ ಉಳಿದಿದೆ. ಬ್ಯಾಟರಿ ಸೇವರ್ ಡಾರ್ಕ್ ಥೀಮ್ ಅನ್ನು ಆನ್ ಮಾಡುತ್ತದೆ, ಹಿನ್ನೆಲೆ ಚಟುವಟಿಕೆಯನ್ನು ನಿರ್ಬಂಧಿಸುತ್ತದೆ ಮತ್ತು ಅಧಿಸೂಚನೆಗಳನ್ನು ವಿಳಂಬಮಾಡುತ್ತದೆ."</string>
+ <string name="battery_low_intro" msgid="5148725009653088790">"ಬ್ಯಾಟರಿ ಸೇವರ್ ಡಾರ್ಕ್ ಥೀಮ್ ಅನ್ನು ಆನ್ ಮಾಡುತ್ತದೆ, ಹಿನ್ನೆಲೆ ಚಟುವಟಿಕೆಯನ್ನು ನಿರ್ಬಂಧಿಸುತ್ತದೆ ಮತ್ತು ಅಧಿಸೂಚನೆಗಳನ್ನು ವಿಳಂಬಮಾಡುತ್ತದೆ."</string>
<string name="battery_low_percent_format" msgid="4276661262843170964">"<xliff:g id="PERCENTAGE">%s</xliff:g> ಉಳಿದಿದೆ"</string>
<string name="invalid_charger_title" msgid="938685362320735167">"USB ಮೂಲಕ ಚಾರ್ಜ್ ಮಾಡಲು ಸಾಧ್ಯವಿಲ್ಲ"</string>
<string name="invalid_charger_text" msgid="2339310107232691577">"ನಿಮ್ಮ ಸಾಧನದೊಂದಿಗೆ ನೀಡಲಾಗಿರುವ ಚಾರ್ಜರ್ ಬಳಸಿ"</string>
<string name="battery_saver_confirmation_title" msgid="1234998463717398453">"ಬ್ಯಾಟರಿ ಸೇವರ್ ಆನ್ ಮಾಡಬೇಕೇ?"</string>
<string name="battery_saver_confirmation_title_generic" msgid="2299231884234959849">"ಬ್ಯಾಟರಿ ಸೇವರ್ ಕುರಿತು"</string>
<string name="battery_saver_confirmation_ok" msgid="5042136476802816494">"ಆನ್ ಮಾಡಿ"</string>
- <string name="battery_saver_start_action" msgid="4553256017945469937">"ಬ್ಯಾಟರಿ ಸೇವರ್ ಆನ್ ಮಾಡಿ"</string>
+ <string name="battery_saver_start_action" msgid="8353766979886287140">"ಆನ್ ಮಾಡಿ"</string>
+ <string name="battery_saver_dismiss_action" msgid="7199342621040014738">"ಬೇಡ"</string>
<string name="status_bar_settings_auto_rotation" msgid="8329080442278431708">"ಪರದೆಯನ್ನು ಸ್ವಯಂ-ತಿರುಗಿಸಿ"</string>
<string name="usb_device_permission_prompt" msgid="4414719028369181772">"<xliff:g id="USB_DEVICE">%2$s</xliff:g> ಪ್ರವೇಶಿಸಲು <xliff:g id="APPLICATION">%1$s</xliff:g> ಅನ್ನು ಅನುಮತಿಸುವುದೇ?"</string>
<string name="usb_device_permission_prompt_warn" msgid="2309129784984063656">"<xliff:g id="USB_DEVICE">%2$s</xliff:g> ಅನ್ನು ಪ್ರವೇಶಿಸಲು <xliff:g id="APPLICATION">%1$s</xliff:g> ಅನ್ನು ಅನುಮತಿಸುವುದೇ?\nಈ ಆ್ಯಪ್ಗೆ ರೆಕಾರ್ಡ್ ಅನುಮತಿಯನ್ನು ನೀಡಲಾಗಿಲ್ಲ, ಆದರೆ ಈ USB ಸಾಧನದ ಮೂಲಕ ಆಡಿಯೊವನ್ನು ಸೆರೆಹಿಡಿಯಬಹುದು."</string>
@@ -133,8 +131,7 @@
<string name="biometric_dialog_face_icon_description_authenticated" msgid="2242167416140740920">"ಮುಖವನ್ನು ದೃಢೀಕರಿಸಲಾಗಿದೆ"</string>
<string name="biometric_dialog_face_icon_description_confirmed" msgid="7918067993953940778">"ದೃಢೀಕರಿಸಲಾಗಿದೆ"</string>
<string name="biometric_dialog_tap_confirm" msgid="9166350738859143358">"ಪೂರ್ಣಗೊಳಿಸಲು ದೃಢೀಕರಿಸಿ ಅನ್ನು ಟ್ಯಾಪ್ ಮಾಡಿ"</string>
- <!-- no translation found for biometric_dialog_tap_confirm_with_face (1597899891472340950) -->
- <skip />
+ <string name="biometric_dialog_tap_confirm_with_face" msgid="1597899891472340950">"ನಿಮ್ಮ ಮುಖವನ್ನು ಬಳಸಿ ಅನ್ಲಾಕ್ ಮಾಡಲಾಗಿದೆ. ಮುಂದುವರಿಯಲು ಒತ್ತಿ."</string>
<string name="biometric_dialog_authenticated" msgid="7337147327545272484">"ದೃಢೀಕರಿಸಲಾಗಿದೆ"</string>
<string name="biometric_dialog_use_pin" msgid="8385294115283000709">"ಪಿನ್ ಬಳಸಿ"</string>
<string name="biometric_dialog_use_pattern" msgid="2315593393167211194">"ಪ್ಯಾಟರ್ನ್ ಬಳಸಿ"</string>
@@ -462,8 +459,8 @@
<string name="wallet_secondary_label_device_locked" msgid="5175862019125370506">"ಬಳಸಲು ಅನ್ಲಾಕ್ ಮಾಡಿ"</string>
<string name="wallet_error_generic" msgid="257704570182963611">"ನಿಮ್ಮ ಕಾರ್ಡ್ಗಳನ್ನು ಪಡೆಯುವಾಗ ಸಮಸ್ಯೆ ಉಂಟಾಗಿದೆ, ನಂತರ ಪುನಃ ಪ್ರಯತ್ನಿಸಿ"</string>
<string name="wallet_lockscreen_settings_label" msgid="3539105300870383570">"ಲಾಕ್ ಸ್ಕ್ರ್ರೀನ್ ಸೆಟ್ಟಿಂಗ್ಗಳು"</string>
- <string name="qr_code_scanner_title" msgid="5660820608548306581">"QR ಕೋಡ್"</string>
- <string name="qr_code_scanner_description" msgid="7937603775306661863">"ಸ್ಕ್ಯಾನ್ ಮಾಡಲು ಟ್ಯಾಪ್ ಮಾಡಿ"</string>
+ <!-- no translation found for qr_code_scanner_title (5290201053875420785) -->
+ <skip />
<string name="status_bar_work" msgid="5238641949837091056">"ಕೆಲಸದ ಪ್ರೊಫೈಲ್"</string>
<string name="status_bar_airplane" msgid="4848702508684541009">"ಏರ್ಪ್ಲೇನ್ ಮೋಡ್"</string>
<string name="zen_alarm_warning" msgid="7844303238486849503">"ನಿಮ್ಮ ಮುಂದಿನ <xliff:g id="WHEN">%1$s</xliff:g> ಅಲಾರಮ್ ಅನ್ನು ನೀವು ಆಲಿಸುವುದಿಲ್ಲ"</string>
@@ -827,6 +824,7 @@
<string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"ಹೊಸ ಸಾಧನವನ್ನು ಜೋಡಿಸಿ"</string>
<string name="media_output_dialog_launch_app_text" msgid="1527413319632586259">"ಈ ಸೆಶನ್ ಕಾಸ್ಟ್ ಮಾಡಲು, ಆ್ಯಪ್ ಅನ್ನು ತೆರೆಯಿರಿ."</string>
<string name="media_output_dialog_unknown_launch_app_name" msgid="1084899329829371336">"ಅಪರಿಚಿತ ಆ್ಯಪ್"</string>
+ <string name="media_output_dialog_button_stop_casting" msgid="6581379537930199189">"ಬಿತ್ತರಿಸುವುದನ್ನು ನಿಲ್ಲಿಸಿ"</string>
<string name="build_number_clip_data_label" msgid="3623176728412560914">"ಬಿಲ್ಡ್ ಸಂಖ್ಯೆ"</string>
<string name="build_number_copy_toast" msgid="877720921605503046">"ಬಿಲ್ಡ್ ಸಂಖ್ಯೆಯನ್ನು ಕ್ಲಿಪ್ಬೋರ್ಡ್ನಲ್ಲಿ ನಕಲಿಸಲಾಗಿದೆ."</string>
<string name="basic_status" msgid="2315371112182658176">"ಸಂಭಾಷಣೆಯನ್ನು ತೆರೆಯಿರಿ"</string>
@@ -916,7 +914,6 @@
<string name="dream_overlay_status_bar_wifi_off" msgid="4497069245055003582">"ವೈ-ಫೈ ಲಭ್ಯವಿಲ್ಲ"</string>
<string name="dream_overlay_status_bar_priority_mode" msgid="5428462123314728739">"ಆದ್ಯತೆ ಮೋಡ್"</string>
<string name="dream_overlay_status_bar_alarm_set" msgid="566707328356590886">"ಅಲಾರಾಂ ಹೊಂದಿಸಲಾಗಿದೆ"</string>
- <string name="dream_overlay_status_bar_assistant_guest_mode_enabled" msgid="3715897096012469615">"Assistant ಅತಿಥಿ ಮೋಡ್ ಅನ್ನು ಸಕ್ರಿಯಗೊಳಿಸಲಾಗಿದೆ"</string>
<string name="dream_overlay_status_bar_camera_mic_off" msgid="3199425257833773569">"ಕ್ಯಾಮರಾ ಮತ್ತು ಮೈಕ್ ಆಫ್ ಆಗಿದೆ"</string>
<string name="dream_overlay_status_bar_notification_indicator" msgid="8091389255691081711">"{count,plural, =1{# ಅಧಿಸೂಚನೆ}one{# ಅಧಿಸೂಚನೆಗಳು}other{# ಅಧಿಸೂಚನೆಗಳು}}"</string>
</resources>
diff --git a/packages/SystemUI/res/values-ko/strings.xml b/packages/SystemUI/res/values-ko/strings.xml
index ba6ef05..8705e71 100644
--- a/packages/SystemUI/res/values-ko/strings.xml
+++ b/packages/SystemUI/res/values-ko/strings.xml
@@ -20,19 +20,17 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_label" msgid="4811759950673118541">"시스템 UI"</string>
- <!-- no translation found for battery_low_title (5319680173344341779) -->
- <skip />
- <!-- no translation found for battery_low_description (3282977755476423966) -->
- <skip />
- <!-- no translation found for battery_low_intro (5148725009653088790) -->
- <skip />
+ <string name="battery_low_title" msgid="5319680173344341779">"절전 모드를 사용 설정하시겠습니까?"</string>
+ <string name="battery_low_description" msgid="3282977755476423966">"배터리가 <xliff:g id="PERCENTAGE">%s</xliff:g> 남았습니다. 절전 모드는 어두운 테마를 사용 설정하고 백그라운드 활동을 제한하며 알림을 지연시킵니다."</string>
+ <string name="battery_low_intro" msgid="5148725009653088790">"절전 모드는 어두운 테마를 사용 설정하고 백그라운드 활동을 제한하며 알림을 지연시킵니다."</string>
<string name="battery_low_percent_format" msgid="4276661262843170964">"<xliff:g id="PERCENTAGE">%s</xliff:g> 남았습니다."</string>
<string name="invalid_charger_title" msgid="938685362320735167">"USB로 충전할 수 없습니다."</string>
<string name="invalid_charger_text" msgid="2339310107232691577">"기기와 함께 제공된 충전기를 사용하세요."</string>
<string name="battery_saver_confirmation_title" msgid="1234998463717398453">"절전 모드를 사용 설정하시겠습니까?"</string>
<string name="battery_saver_confirmation_title_generic" msgid="2299231884234959849">"절전 모드 정보"</string>
<string name="battery_saver_confirmation_ok" msgid="5042136476802816494">"사용"</string>
- <string name="battery_saver_start_action" msgid="4553256017945469937">"절전 모드 사용 설정"</string>
+ <string name="battery_saver_start_action" msgid="8353766979886287140">"사용"</string>
+ <string name="battery_saver_dismiss_action" msgid="7199342621040014738">"사용 안함"</string>
<string name="status_bar_settings_auto_rotation" msgid="8329080442278431708">"화면 자동 회전"</string>
<string name="usb_device_permission_prompt" msgid="4414719028369181772">"<xliff:g id="APPLICATION">%1$s</xliff:g> 앱이 <xliff:g id="USB_DEVICE">%2$s</xliff:g>에 액세스하도록 허용하시겠습니까?"</string>
<string name="usb_device_permission_prompt_warn" msgid="2309129784984063656">"<xliff:g id="APPLICATION">%1$s</xliff:g>에서 <xliff:g id="USB_DEVICE">%2$s</xliff:g>에 액세스하도록 허용하시겠습니까?\n이 앱에는 녹음 권한이 부여되지 않았지만, 이 USB 기기를 통해 오디오를 녹음할 수 있습니다."</string>
@@ -133,8 +131,7 @@
<string name="biometric_dialog_face_icon_description_authenticated" msgid="2242167416140740920">"얼굴이 인증되었습니다."</string>
<string name="biometric_dialog_face_icon_description_confirmed" msgid="7918067993953940778">"확인함"</string>
<string name="biometric_dialog_tap_confirm" msgid="9166350738859143358">"완료하려면 확인을 탭하세요."</string>
- <!-- no translation found for biometric_dialog_tap_confirm_with_face (1597899891472340950) -->
- <skip />
+ <string name="biometric_dialog_tap_confirm_with_face" msgid="1597899891472340950">"얼굴 인식으로 잠금 해제했습니다. 계속하려면 누르세요."</string>
<string name="biometric_dialog_authenticated" msgid="7337147327545272484">"인증됨"</string>
<string name="biometric_dialog_use_pin" msgid="8385294115283000709">"PIN 사용"</string>
<string name="biometric_dialog_use_pattern" msgid="2315593393167211194">"패턴 사용"</string>
@@ -462,8 +459,8 @@
<string name="wallet_secondary_label_device_locked" msgid="5175862019125370506">"잠금 해제하여 사용"</string>
<string name="wallet_error_generic" msgid="257704570182963611">"카드를 가져오는 중에 문제가 발생했습니다. 나중에 다시 시도해 보세요."</string>
<string name="wallet_lockscreen_settings_label" msgid="3539105300870383570">"잠금 화면 설정"</string>
- <string name="qr_code_scanner_title" msgid="5660820608548306581">"QR 코드"</string>
- <string name="qr_code_scanner_description" msgid="7937603775306661863">"탭하여 스캔"</string>
+ <!-- no translation found for qr_code_scanner_title (5290201053875420785) -->
+ <skip />
<string name="status_bar_work" msgid="5238641949837091056">"직장 프로필"</string>
<string name="status_bar_airplane" msgid="4848702508684541009">"비행기 모드"</string>
<string name="zen_alarm_warning" msgid="7844303238486849503">"<xliff:g id="WHEN">%1$s</xliff:g>에 다음 알람을 들을 수 없습니다."</string>
@@ -827,6 +824,7 @@
<string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"새 기기와 페어링"</string>
<string name="media_output_dialog_launch_app_text" msgid="1527413319632586259">"세션을 전송하려면 앱을 열어 주세요"</string>
<string name="media_output_dialog_unknown_launch_app_name" msgid="1084899329829371336">"알 수 없는 앱"</string>
+ <string name="media_output_dialog_button_stop_casting" msgid="6581379537930199189">"전송 중지"</string>
<string name="build_number_clip_data_label" msgid="3623176728412560914">"빌드 번호"</string>
<string name="build_number_copy_toast" msgid="877720921605503046">"빌드 번호가 클립보드에 복사되었습니다."</string>
<string name="basic_status" msgid="2315371112182658176">"대화 열기"</string>
@@ -916,8 +914,6 @@
<string name="dream_overlay_status_bar_wifi_off" msgid="4497069245055003582">"Wi‑Fi를 이용할 수 없습니다."</string>
<string name="dream_overlay_status_bar_priority_mode" msgid="5428462123314728739">"우선순위 모드입니다."</string>
<string name="dream_overlay_status_bar_alarm_set" msgid="566707328356590886">"알람이 설정되었습니다."</string>
- <string name="dream_overlay_status_bar_assistant_guest_mode_enabled" msgid="3715897096012469615">"어시스턴트 게스트 모드가 사용 설정되었습니다."</string>
<string name="dream_overlay_status_bar_camera_mic_off" msgid="3199425257833773569">"카메라 및 마이크가 사용 중지되었습니다."</string>
- <!-- no translation found for dream_overlay_status_bar_notification_indicator (8091389255691081711) -->
- <skip />
+ <string name="dream_overlay_status_bar_notification_indicator" msgid="8091389255691081711">"{count,plural, =1{알림 #개}other{알림 #개}}"</string>
</resources>
diff --git a/packages/SystemUI/res/values-ky/strings.xml b/packages/SystemUI/res/values-ky/strings.xml
index a31ab6d..6187f3a 100644
--- a/packages/SystemUI/res/values-ky/strings.xml
+++ b/packages/SystemUI/res/values-ky/strings.xml
@@ -20,19 +20,17 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_label" msgid="4811759950673118541">"Тутум UI"</string>
- <!-- no translation found for battery_low_title (5319680173344341779) -->
- <skip />
- <!-- no translation found for battery_low_description (3282977755476423966) -->
- <skip />
- <!-- no translation found for battery_low_intro (5148725009653088790) -->
- <skip />
+ <string name="battery_low_title" msgid="5319680173344341779">"Батареяны үнөмдөгүч режими күйгүзүлсүнбү?"</string>
+ <string name="battery_low_description" msgid="3282977755476423966">"Батареянын деңгээли: <xliff:g id="PERCENTAGE">%s</xliff:g>. Батареяны үнөмдөгүч режими Караңгы теманы күйгүзүп, фондогу аракеттерди чектеп, билдирмелерди кечиктирет."</string>
+ <string name="battery_low_intro" msgid="5148725009653088790">"Батареяны үнөмдөгүч режими Караңгы теманы күйгүзүп, фондогу аракеттерди чектеп, билдирмелерди кечиктирет."</string>
<string name="battery_low_percent_format" msgid="4276661262843170964">"<xliff:g id="PERCENTAGE">%s</xliff:g> калды"</string>
<string name="invalid_charger_title" msgid="938685362320735167">"USB аркылуу кубатталбай жатат"</string>
<string name="invalid_charger_text" msgid="2339310107232691577">"Түзмөгүңүз менен келген кубаттагычты колдонуңуз"</string>
<string name="battery_saver_confirmation_title" msgid="1234998463717398453">"Батареяны үнөмдөө режимин күйгүзөсүзбү?"</string>
<string name="battery_saver_confirmation_title_generic" msgid="2299231884234959849">"Батареяны үнөмдөгүч режими жөнүндө маалымат"</string>
<string name="battery_saver_confirmation_ok" msgid="5042136476802816494">"Күйгүзүү"</string>
- <string name="battery_saver_start_action" msgid="4553256017945469937">"Батареяны үнөмдөгүчтү күйгүзүү"</string>
+ <string name="battery_saver_start_action" msgid="8353766979886287140">"Күйгүзүү"</string>
+ <string name="battery_saver_dismiss_action" msgid="7199342621040014738">"Жок, рахмат"</string>
<string name="status_bar_settings_auto_rotation" msgid="8329080442278431708">"Экранды авто буруу"</string>
<string name="usb_device_permission_prompt" msgid="4414719028369181772">"<xliff:g id="APPLICATION">%1$s</xliff:g> колдонмосу <xliff:g id="USB_DEVICE">%2$s</xliff:g> түзмөгүн колдоно берсинби?"</string>
<string name="usb_device_permission_prompt_warn" msgid="2309129784984063656">"<xliff:g id="APPLICATION">%1$s</xliff:g> колдонмосу үчүн <xliff:g id="USB_DEVICE">%2$s</xliff:g> түзмөгүнө мүмкүнчүлүк алууга уруксат бересизби?\nБул колдонмонун жаздырууга уруксаты жок, бирок бул USB түзмөгү аркылуу аудиону жаздыра алат."</string>
@@ -133,8 +131,7 @@
<string name="biometric_dialog_face_icon_description_authenticated" msgid="2242167416140740920">"Жүздүн аныктыгы текшерилди"</string>
<string name="biometric_dialog_face_icon_description_confirmed" msgid="7918067993953940778">"Ырасталды"</string>
<string name="biometric_dialog_tap_confirm" msgid="9166350738859143358">"Бүтүрүү үчүн \"Ырастоо\" баскычын басыңыз"</string>
- <!-- no translation found for biometric_dialog_tap_confirm_with_face (1597899891472340950) -->
- <skip />
+ <string name="biometric_dialog_tap_confirm_with_face" msgid="1597899891472340950">"Жүзүңүз менен ачылды. Улантуу үчүн басыңыз."</string>
<string name="biometric_dialog_authenticated" msgid="7337147327545272484">"Аныктыгы текшерилди"</string>
<string name="biometric_dialog_use_pin" msgid="8385294115283000709">"PIN кодду колдонуу"</string>
<string name="biometric_dialog_use_pattern" msgid="2315593393167211194">"Графикалык ачкычты колдонуу"</string>
@@ -462,8 +459,8 @@
<string name="wallet_secondary_label_device_locked" msgid="5175862019125370506">"Колдонуу үчүн кулпусун ачыңыз"</string>
<string name="wallet_error_generic" msgid="257704570182963611">"Кыйытмаларды алууда ката кетти. Бир аздан кийин кайталап көрүңүз."</string>
<string name="wallet_lockscreen_settings_label" msgid="3539105300870383570">"Кулпуланган экран жөндөөлөрү"</string>
- <string name="qr_code_scanner_title" msgid="5660820608548306581">"QR коду"</string>
- <string name="qr_code_scanner_description" msgid="7937603775306661863">"Скандоо үчүн таптап коюңуз"</string>
+ <!-- no translation found for qr_code_scanner_title (5290201053875420785) -->
+ <skip />
<string name="status_bar_work" msgid="5238641949837091056">"Жумуш профили"</string>
<string name="status_bar_airplane" msgid="4848702508684541009">"Учак режими"</string>
<string name="zen_alarm_warning" msgid="7844303238486849503">"<xliff:g id="WHEN">%1$s</xliff:g> боло турган кийинки эскертмени укпайсыз"</string>
@@ -827,6 +824,7 @@
<string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"Жаңы түзмөктү жупташтыруу"</string>
<string name="media_output_dialog_launch_app_text" msgid="1527413319632586259">"Бул сеансты тышкы экранга чыгаруу үчүн колдонмону ачыңыз."</string>
<string name="media_output_dialog_unknown_launch_app_name" msgid="1084899329829371336">"Белгисиз колдонмо"</string>
+ <string name="media_output_dialog_button_stop_casting" msgid="6581379537930199189">"Тышкы экранга чыгарууну токтотуу"</string>
<string name="build_number_clip_data_label" msgid="3623176728412560914">"Курама номери"</string>
<string name="build_number_copy_toast" msgid="877720921605503046">"Курама номери алмашуу буферине көчүрүлдү."</string>
<string name="basic_status" msgid="2315371112182658176">"Ачык сүйлөшүү"</string>
@@ -916,7 +914,6 @@
<string name="dream_overlay_status_bar_wifi_off" msgid="4497069245055003582">"Wi‑Fi жеткиликсиз"</string>
<string name="dream_overlay_status_bar_priority_mode" msgid="5428462123314728739">"Маанилүү сүйлөшүүлөр режими"</string>
<string name="dream_overlay_status_bar_alarm_set" msgid="566707328356590886">"Ойготкуч коюлду"</string>
- <string name="dream_overlay_status_bar_assistant_guest_mode_enabled" msgid="3715897096012469615">"Жардамчынын конок режими иштетилди"</string>
<string name="dream_overlay_status_bar_camera_mic_off" msgid="3199425257833773569">"Камера жана микрофон өчүк"</string>
<string name="dream_overlay_status_bar_notification_indicator" msgid="8091389255691081711">"{count,plural, =1{# билдирме}other{# билдирме}}"</string>
</resources>
diff --git a/packages/SystemUI/res/values-lo/strings.xml b/packages/SystemUI/res/values-lo/strings.xml
index 204e3d9..3343bcf 100644
--- a/packages/SystemUI/res/values-lo/strings.xml
+++ b/packages/SystemUI/res/values-lo/strings.xml
@@ -20,19 +20,17 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_label" msgid="4811759950673118541">"ສ່ວນຕິດຕໍ່ຜູ້ໃຊ້ຂອງລະບົບ"</string>
- <!-- no translation found for battery_low_title (5319680173344341779) -->
- <skip />
- <!-- no translation found for battery_low_description (3282977755476423966) -->
- <skip />
- <!-- no translation found for battery_low_intro (5148725009653088790) -->
- <skip />
+ <string name="battery_low_title" msgid="5319680173344341779">"ເປີດໃຊ້ຕົວປະຢັດແບັດເຕີຣີບໍ?"</string>
+ <string name="battery_low_description" msgid="3282977755476423966">"ທ່ານມີແບັດເຕີຣີເຫຼືອ <xliff:g id="PERCENTAGE">%s</xliff:g>. ຕົວປະຢັດແບັດເຕີຣີຈະເປີດໃຊ້ຮູບແບບສີສັນມືດ, ຈຳກັດການເຄື່ອນໄຫວໃນພື້ນຫຼັງ ແລະ ເລື່ອນການແຈ້ງເຕືອນອອກໄປ."</string>
+ <string name="battery_low_intro" msgid="5148725009653088790">"ຕົວປະຢັດແບັດເຕີຣີຈະເປີດໃຊ້ຮູບແບບສີສັນມືດ, ຈຳກັດການເຄື່ອນໄຫວໃນພື້ນຫຼັງ ແລະ ເລື່ອນການແຈ້ງເຕືອນອອກໄປ."</string>
<string name="battery_low_percent_format" msgid="4276661262843170964">"ຍັງເຫຼືອ <xliff:g id="PERCENTAGE">%s</xliff:g>"</string>
<string name="invalid_charger_title" msgid="938685362320735167">"ບໍ່ສາມາດສາກຜ່ານ USB ໄດ້"</string>
<string name="invalid_charger_text" msgid="2339310107232691577">"ກະລຸນາໃຊ້ຕົວສາກທີ່ມາພ້ອມກັບອຸປະກອນຂອງທ່ານ"</string>
<string name="battery_saver_confirmation_title" msgid="1234998463717398453">"ເປີດໃຊ້ຕົວປະຢັດແບັດເຕີຣີບໍ?"</string>
<string name="battery_saver_confirmation_title_generic" msgid="2299231884234959849">"ກ່ຽວກັບຕົວປະຢັດແບັດເຕີຣີ"</string>
<string name="battery_saver_confirmation_ok" msgid="5042136476802816494">"ເປີດໃຊ້"</string>
- <string name="battery_saver_start_action" msgid="4553256017945469937">"ເປີດໃຊ້ຕົວປະຢັດແບັດເຕີຣີ"</string>
+ <string name="battery_saver_start_action" msgid="8353766979886287140">"ເປີດໃຊ້"</string>
+ <string name="battery_saver_dismiss_action" msgid="7199342621040014738">"ບໍ່, ຂອບໃຈ"</string>
<string name="status_bar_settings_auto_rotation" msgid="8329080442278431708">"ໝຸນໜ້າຈໍອັດຕະໂນມັດ"</string>
<string name="usb_device_permission_prompt" msgid="4414719028369181772">"ອະນຸຍາດໃຫ້ <xliff:g id="APPLICATION">%1$s</xliff:g> ເຂົ້າເຖິງ <xliff:g id="USB_DEVICE">%2$s</xliff:g> ໄດ້ບໍ?"</string>
<string name="usb_device_permission_prompt_warn" msgid="2309129784984063656">"ອະນຸຍາດໃຫ້ <xliff:g id="APPLICATION">%1$s</xliff:g> ເຂົ້າເຖິງ <xliff:g id="USB_DEVICE">%2$s</xliff:g> ໄດ້ບໍ?\nແອັບນີ້ບໍ່ໄດ້ຮັບອະນຸາດໃຫ້ບັນທຶກໄດ້ແຕ່ສາມາດບັນທຶກສຽງໄດ້ຜ່ານອຸປະກອນ USB ນີ້."</string>
@@ -133,8 +131,7 @@
<string name="biometric_dialog_face_icon_description_authenticated" msgid="2242167416140740920">"ພິສູດຢືນຢັນໃບໜ້າແລ້ວ"</string>
<string name="biometric_dialog_face_icon_description_confirmed" msgid="7918067993953940778">"ຢືນຢັນແລ້ວ"</string>
<string name="biometric_dialog_tap_confirm" msgid="9166350738859143358">"ແຕະຢືນຢັນເພື່ອສຳເລັດ"</string>
- <!-- no translation found for biometric_dialog_tap_confirm_with_face (1597899891472340950) -->
- <skip />
+ <string name="biometric_dialog_tap_confirm_with_face" msgid="1597899891472340950">"ປົດລັອກດ້ວຍໜ້າຂອງທ່ານແລ້ວ. ກົດເພື່ອສືບຕໍ່."</string>
<string name="biometric_dialog_authenticated" msgid="7337147327545272484">"ຮັບຮອງຄວາມຖືກຕ້ອງແລ້ວ"</string>
<string name="biometric_dialog_use_pin" msgid="8385294115283000709">"ໃຊ້ PIN"</string>
<string name="biometric_dialog_use_pattern" msgid="2315593393167211194">"ໃຊ້ຮູບແບບ"</string>
@@ -462,8 +459,8 @@
<string name="wallet_secondary_label_device_locked" msgid="5175862019125370506">"ປົດລັອກເພື່ອໃຊ້"</string>
<string name="wallet_error_generic" msgid="257704570182963611">"ເກີດບັນຫາໃນການໂຫຼດບັດຂອງທ່ານ, ກະລຸນາລອງໃໝ່ໃນພາຍຫຼັງ"</string>
<string name="wallet_lockscreen_settings_label" msgid="3539105300870383570">"ການຕັ້ງຄ່າໜ້າຈໍລັອກ"</string>
- <string name="qr_code_scanner_title" msgid="5660820608548306581">"ລະຫັດ QR"</string>
- <string name="qr_code_scanner_description" msgid="7937603775306661863">"ແຕະເພື່ອສະແກນ"</string>
+ <!-- no translation found for qr_code_scanner_title (5290201053875420785) -->
+ <skip />
<string name="status_bar_work" msgid="5238641949837091056">"ໂປຣໄຟລ໌ບ່ອນເຮັດວຽກ"</string>
<string name="status_bar_airplane" msgid="4848702508684541009">"ໂໝດເຮືອບິນ"</string>
<string name="zen_alarm_warning" msgid="7844303238486849503">"ທ່ານຈະບໍ່ໄດ້ຍິນສຽງໂມງປ <xliff:g id="WHEN">%1$s</xliff:g>"</string>
@@ -827,6 +824,7 @@
<string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"ຈັບຄູ່ອຸປະກອນໃໝ່"</string>
<string name="media_output_dialog_launch_app_text" msgid="1527413319632586259">"ເພື່ອສົ່ງສັນຍານເຊດຊັນນີ້, ກະລຸນາເປີດແອັບ."</string>
<string name="media_output_dialog_unknown_launch_app_name" msgid="1084899329829371336">"ແອັບທີ່ບໍ່ຮູ້ຈັກ"</string>
+ <string name="media_output_dialog_button_stop_casting" msgid="6581379537930199189">"ຢຸດການສົ່ງສັນຍານ"</string>
<string name="build_number_clip_data_label" msgid="3623176728412560914">"ໝາຍເລກສ້າງ"</string>
<string name="build_number_copy_toast" msgid="877720921605503046">"ສຳເນົາໝາຍເລກສ້າງໄປໃສ່ຄລິບບອດແລ້ວ."</string>
<string name="basic_status" msgid="2315371112182658176">"ເປີດການສົນທະນາ"</string>
@@ -916,8 +914,6 @@
<string name="dream_overlay_status_bar_wifi_off" msgid="4497069245055003582">"ບໍ່ສາມາດໃຊ້ Wi‑Fi ໄດ້"</string>
<string name="dream_overlay_status_bar_priority_mode" msgid="5428462123314728739">"ໂໝດຄວາມສຳຄັນ"</string>
<string name="dream_overlay_status_bar_alarm_set" msgid="566707328356590886">"ຕັ້ງໂມງປຸກແລ້ວ"</string>
- <string name="dream_overlay_status_bar_assistant_guest_mode_enabled" msgid="3715897096012469615">"ເປີດການນຳໃຊ້ໂໝດແຂກຜູ້ຊ່ວຍແລ້ວ"</string>
<string name="dream_overlay_status_bar_camera_mic_off" msgid="3199425257833773569">"ປິດກ້ອງຖ່າຍຮູບ ແລະ ໄມແລ້ວ"</string>
- <!-- no translation found for dream_overlay_status_bar_notification_indicator (8091389255691081711) -->
- <skip />
+ <string name="dream_overlay_status_bar_notification_indicator" msgid="8091389255691081711">"{count,plural, =1{# ການແຈ້ງເຕືອນ}other{# ການແຈ້ງເຕືອນ}}"</string>
</resources>
diff --git a/packages/SystemUI/res/values-lt/strings.xml b/packages/SystemUI/res/values-lt/strings.xml
index 6bcfa0e..547d250 100644
--- a/packages/SystemUI/res/values-lt/strings.xml
+++ b/packages/SystemUI/res/values-lt/strings.xml
@@ -20,19 +20,17 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_label" msgid="4811759950673118541">"Sistemos NS"</string>
- <!-- no translation found for battery_low_title (5319680173344341779) -->
- <skip />
- <!-- no translation found for battery_low_description (3282977755476423966) -->
- <skip />
- <!-- no translation found for battery_low_intro (5148725009653088790) -->
- <skip />
+ <string name="battery_low_title" msgid="5319680173344341779">"Įjungti Akumuliatoriaus tausojimo priemonę?"</string>
+ <string name="battery_low_description" msgid="3282977755476423966">"Liko <xliff:g id="PERCENTAGE">%s</xliff:g> akumuliatoriaus energijos. Kai naudojama Akumuliatoriaus tausojimo priemonė, įjungiama Tamsioji tema, apribojama veikla fone ir atidedami pranešimai."</string>
+ <string name="battery_low_intro" msgid="5148725009653088790">"Kai naudojama Akumuliatoriaus tausojimo priemonė, įjungiama Tamsioji tema, apribojama veikla fone ir atidedami pranešimai."</string>
<string name="battery_low_percent_format" msgid="4276661262843170964">"Liko <xliff:g id="PERCENTAGE">%s</xliff:g>"</string>
<string name="invalid_charger_title" msgid="938685362320735167">"Negalima įkrauti naudojant USB"</string>
<string name="invalid_charger_text" msgid="2339310107232691577">"Naudokite originalų su įrenginiu pateiktą įkroviklį"</string>
<string name="battery_saver_confirmation_title" msgid="1234998463717398453">"Įjungti Akumuliatoriaus tausojimo priemonę?"</string>
<string name="battery_saver_confirmation_title_generic" msgid="2299231884234959849">"Apie Akumuliatoriaus tausojimo priemonę"</string>
<string name="battery_saver_confirmation_ok" msgid="5042136476802816494">"Įjungti"</string>
- <string name="battery_saver_start_action" msgid="4553256017945469937">"Įjungti Akumuliatoriaus tausojimo priemonę"</string>
+ <string name="battery_saver_start_action" msgid="8353766979886287140">"Įjungti"</string>
+ <string name="battery_saver_dismiss_action" msgid="7199342621040014738">"Ne, ačiū"</string>
<string name="status_bar_settings_auto_rotation" msgid="8329080442278431708">"Automatiškai sukti ekraną"</string>
<string name="usb_device_permission_prompt" msgid="4414719028369181772">"Leisti „<xliff:g id="APPLICATION">%1$s</xliff:g>“ pasiekti įrenginį (<xliff:g id="USB_DEVICE">%2$s</xliff:g>)?"</string>
<string name="usb_device_permission_prompt_warn" msgid="2309129784984063656">"Leisti „<xliff:g id="APPLICATION">%1$s</xliff:g>“ pasiekti įrenginį (<xliff:g id="USB_DEVICE">%2$s</xliff:g>)?\nŠiai programai nebuvo suteiktas leidimas įrašyti, bet ji gali užfiksuoti garsą per šį USB įrenginį."</string>
@@ -133,8 +131,7 @@
<string name="biometric_dialog_face_icon_description_authenticated" msgid="2242167416140740920">"Veidas autentifikuotas"</string>
<string name="biometric_dialog_face_icon_description_confirmed" msgid="7918067993953940778">"Patvirtinta"</string>
<string name="biometric_dialog_tap_confirm" msgid="9166350738859143358">"Paliesk. „Patvirtinti“, kad užbaigtumėte"</string>
- <!-- no translation found for biometric_dialog_tap_confirm_with_face (1597899891472340950) -->
- <skip />
+ <string name="biometric_dialog_tap_confirm_with_face" msgid="1597899891472340950">"Atrakinta pagal veidą. Paspauskite, jei norite tęsti."</string>
<string name="biometric_dialog_authenticated" msgid="7337147327545272484">"Autentifikuota"</string>
<string name="biometric_dialog_use_pin" msgid="8385294115283000709">"Naudoti PIN kodą"</string>
<string name="biometric_dialog_use_pattern" msgid="2315593393167211194">"Naudoti atrakinimo piešinį"</string>
@@ -468,8 +465,8 @@
<string name="wallet_secondary_label_device_locked" msgid="5175862019125370506">"Atrakinti, kad būtų galima naudoti"</string>
<string name="wallet_error_generic" msgid="257704570182963611">"Gaunant korteles kilo problema, bandykite dar kartą vėliau"</string>
<string name="wallet_lockscreen_settings_label" msgid="3539105300870383570">"Užrakinimo ekrano nustatymai"</string>
- <string name="qr_code_scanner_title" msgid="5660820608548306581">"QR kodas"</string>
- <string name="qr_code_scanner_description" msgid="7937603775306661863">"Palieskite, kad nuskaitytumėte"</string>
+ <!-- no translation found for qr_code_scanner_title (5290201053875420785) -->
+ <skip />
<string name="status_bar_work" msgid="5238641949837091056">"Darbo profilis"</string>
<string name="status_bar_airplane" msgid="4848702508684541009">"Lėktuvo režimas"</string>
<string name="zen_alarm_warning" msgid="7844303238486849503">"Negirdėsite kito signalo <xliff:g id="WHEN">%1$s</xliff:g>"</string>
@@ -839,6 +836,7 @@
<string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"Naujo įrenginio susiejimas"</string>
<string name="media_output_dialog_launch_app_text" msgid="1527413319632586259">"Jei norite perduoti šį seansą, atidarykite programą."</string>
<string name="media_output_dialog_unknown_launch_app_name" msgid="1084899329829371336">"Nežinoma programa"</string>
+ <string name="media_output_dialog_button_stop_casting" msgid="6581379537930199189">"Sustabdyti perdavimą"</string>
<string name="build_number_clip_data_label" msgid="3623176728412560914">"Versijos numeris"</string>
<string name="build_number_copy_toast" msgid="877720921605503046">"Versijos numeris nukopijuotas į iškarpinę."</string>
<string name="basic_status" msgid="2315371112182658176">"Atidaryti pokalbį"</string>
@@ -930,8 +928,6 @@
<string name="dream_overlay_status_bar_wifi_off" msgid="4497069245055003582">"„Wi‑Fi“ ryšys nepasiekiamas"</string>
<string name="dream_overlay_status_bar_priority_mode" msgid="5428462123314728739">"Prioriteto režimas"</string>
<string name="dream_overlay_status_bar_alarm_set" msgid="566707328356590886">"Signalas nustatytas"</string>
- <string name="dream_overlay_status_bar_assistant_guest_mode_enabled" msgid="3715897096012469615">"Įgalintas Padėjėjo svečio režimas"</string>
<string name="dream_overlay_status_bar_camera_mic_off" msgid="3199425257833773569">"Vaizdo kamera ir mikrofonas išjungti"</string>
- <!-- no translation found for dream_overlay_status_bar_notification_indicator (8091389255691081711) -->
- <skip />
+ <string name="dream_overlay_status_bar_notification_indicator" msgid="8091389255691081711">"{count,plural, =1{# pranešimas}one{# pranešimas}few{# pranešimai}many{# pranešimo}other{# pranešimų}}"</string>
</resources>
diff --git a/packages/SystemUI/res/values-lv/strings.xml b/packages/SystemUI/res/values-lv/strings.xml
index 286cdec..5e79f75 100644
--- a/packages/SystemUI/res/values-lv/strings.xml
+++ b/packages/SystemUI/res/values-lv/strings.xml
@@ -20,19 +20,17 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_label" msgid="4811759950673118541">"Sistēmas UI"</string>
- <!-- no translation found for battery_low_title (5319680173344341779) -->
- <skip />
- <!-- no translation found for battery_low_description (3282977755476423966) -->
- <skip />
- <!-- no translation found for battery_low_intro (5148725009653088790) -->
- <skip />
+ <string name="battery_low_title" msgid="5319680173344341779">"Vai ieslēgt akumulatora enerģijas taupīšanas režīmu?"</string>
+ <string name="battery_low_description" msgid="3282977755476423966">"Atlikušais akumulatora uzlādes līmenis: <xliff:g id="PERCENTAGE">%s</xliff:g>. Akumulatora enerģijas taupīšanas režīmā tiek ieslēgts tumšais motīvs, ierobežotas darbības fonā un aizkavēti paziņojumi."</string>
+ <string name="battery_low_intro" msgid="5148725009653088790">"Akumulatora enerģijas taupīšanas režīmā tiek ieslēgts tumšais motīvs, ierobežotas darbības fonā un aizkavēti paziņojumi."</string>
<string name="battery_low_percent_format" msgid="4276661262843170964">"Atlikuši <xliff:g id="PERCENTAGE">%s</xliff:g>"</string>
<string name="invalid_charger_title" msgid="938685362320735167">"Nevar veikt uzlādi, izmantojot USB"</string>
<string name="invalid_charger_text" msgid="2339310107232691577">"Izmantojiet ierīces komplektācijā iekļauto lādētāju"</string>
<string name="battery_saver_confirmation_title" msgid="1234998463717398453">"Vai ieslēgt akumulatora enerģijas taupīšanas režīmu?"</string>
<string name="battery_saver_confirmation_title_generic" msgid="2299231884234959849">"Par akumulatora enerģijas taupīšanas režīmu"</string>
<string name="battery_saver_confirmation_ok" msgid="5042136476802816494">"Ieslēgt"</string>
- <string name="battery_saver_start_action" msgid="4553256017945469937">"Ieslēgt akumulatora enerģijas taupīšanas režīmu"</string>
+ <string name="battery_saver_start_action" msgid="8353766979886287140">"Ieslēgt"</string>
+ <string name="battery_saver_dismiss_action" msgid="7199342621040014738">"Nē, paldies"</string>
<string name="status_bar_settings_auto_rotation" msgid="8329080442278431708">"Automātiska ekrāna pagriešana"</string>
<string name="usb_device_permission_prompt" msgid="4414719028369181772">"Vai atļaut lietotnei <xliff:g id="APPLICATION">%1$s</xliff:g> piekļūt šai ierīcei: <xliff:g id="USB_DEVICE">%2$s</xliff:g>?"</string>
<string name="usb_device_permission_prompt_warn" msgid="2309129784984063656">"Vai atļaut lietotnei <xliff:g id="APPLICATION">%1$s</xliff:g> piekļūt ierīcei “<xliff:g id="USB_DEVICE">%2$s</xliff:g>”?\nŠai lietotnei nav piešķirta ierakstīšanas atļauja, taču tā varētu tvert audio, izmantojot šo USB ierīci."</string>
@@ -133,8 +131,7 @@
<string name="biometric_dialog_face_icon_description_authenticated" msgid="2242167416140740920">"Seja autentificēta"</string>
<string name="biometric_dialog_face_icon_description_confirmed" msgid="7918067993953940778">"Apstiprināts"</string>
<string name="biometric_dialog_tap_confirm" msgid="9166350738859143358">"Lai pabeigtu, pieskarieties Apstiprināt"</string>
- <!-- no translation found for biometric_dialog_tap_confirm_with_face (1597899891472340950) -->
- <skip />
+ <string name="biometric_dialog_tap_confirm_with_face" msgid="1597899891472340950">"Sākta autorizācija pēc sejas. Nospiediet, lai turpinātu."</string>
<string name="biometric_dialog_authenticated" msgid="7337147327545272484">"Autentifikācija veikta"</string>
<string name="biometric_dialog_use_pin" msgid="8385294115283000709">"Izmantot PIN"</string>
<string name="biometric_dialog_use_pattern" msgid="2315593393167211194">"Izmantot kombināciju"</string>
@@ -465,8 +462,8 @@
<string name="wallet_secondary_label_device_locked" msgid="5175862019125370506">"Lai izmantotu, atbloķējiet ekrānu"</string>
<string name="wallet_error_generic" msgid="257704570182963611">"Ienesot jūsu kartes, radās problēma. Lūdzu, vēlāk mēģiniet vēlreiz."</string>
<string name="wallet_lockscreen_settings_label" msgid="3539105300870383570">"Bloķēšanas ekrāna iestatījumi"</string>
- <string name="qr_code_scanner_title" msgid="5660820608548306581">"Ātrās atbildes kods"</string>
- <string name="qr_code_scanner_description" msgid="7937603775306661863">"Pieskarieties, lai skenētu"</string>
+ <!-- no translation found for qr_code_scanner_title (5290201053875420785) -->
+ <skip />
<string name="status_bar_work" msgid="5238641949837091056">"Darba profils"</string>
<string name="status_bar_airplane" msgid="4848702508684541009">"Lidojuma režīms"</string>
<string name="zen_alarm_warning" msgid="7844303238486849503">"Nākamais signāls (<xliff:g id="WHEN">%1$s</xliff:g>) netiks atskaņots."</string>
@@ -833,6 +830,7 @@
<string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"Savienošana pārī ar jaunu ierīci"</string>
<string name="media_output_dialog_launch_app_text" msgid="1527413319632586259">"Lai apraidītu šo sesiju, lūdzu, atveriet lietotni."</string>
<string name="media_output_dialog_unknown_launch_app_name" msgid="1084899329829371336">"Nezināma lietotne"</string>
+ <string name="media_output_dialog_button_stop_casting" msgid="6581379537930199189">"Apturēt apraidi"</string>
<string name="build_number_clip_data_label" msgid="3623176728412560914">"Versijas numurs"</string>
<string name="build_number_copy_toast" msgid="877720921605503046">"Versijas numurs ir kopēts starpliktuvē."</string>
<string name="basic_status" msgid="2315371112182658176">"Atvērt sarunu"</string>
@@ -923,8 +921,6 @@
<string name="dream_overlay_status_bar_wifi_off" msgid="4497069245055003582">"Wi‑Fi nav pieejams"</string>
<string name="dream_overlay_status_bar_priority_mode" msgid="5428462123314728739">"Prioritātes režīms"</string>
<string name="dream_overlay_status_bar_alarm_set" msgid="566707328356590886">"Signāls ir iestatīts"</string>
- <string name="dream_overlay_status_bar_assistant_guest_mode_enabled" msgid="3715897096012469615">"Asistenta viesa režīms ir iespējots"</string>
<string name="dream_overlay_status_bar_camera_mic_off" msgid="3199425257833773569">"Kamera un mikrofons ir izslēgti"</string>
- <!-- no translation found for dream_overlay_status_bar_notification_indicator (8091389255691081711) -->
- <skip />
+ <string name="dream_overlay_status_bar_notification_indicator" msgid="8091389255691081711">"{count,plural, =1{# paziņojums}zero{# paziņojumu}one{# paziņojums}other{# paziņojumi}}"</string>
</resources>
diff --git a/packages/SystemUI/res/values-mk/strings.xml b/packages/SystemUI/res/values-mk/strings.xml
index ffa0e58..0bde00b 100644
--- a/packages/SystemUI/res/values-mk/strings.xml
+++ b/packages/SystemUI/res/values-mk/strings.xml
@@ -20,19 +20,17 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_label" msgid="4811759950673118541">"Кориснички интерфејс на систем"</string>
- <!-- no translation found for battery_low_title (5319680173344341779) -->
- <skip />
- <!-- no translation found for battery_low_description (3282977755476423966) -->
- <skip />
- <!-- no translation found for battery_low_intro (5148725009653088790) -->
- <skip />
+ <string name="battery_low_title" msgid="5319680173344341779">"Да се вклучи „Штедачот на батерија“?"</string>
+ <string name="battery_low_description" msgid="3282977755476423966">"Имате уште <xliff:g id="PERCENTAGE">%s</xliff:g> батерија. „Штедачот на батерија“ ја вклучува „Темната тема“, ја ограничува активноста во заднина и ги одложува известувањата."</string>
+ <string name="battery_low_intro" msgid="5148725009653088790">"„Штедачот на батерија“ ја вклучува „Темната тема“, ја ограничува активноста во заднина и ги одложува известувањата."</string>
<string name="battery_low_percent_format" msgid="4276661262843170964">"Преостануваат <xliff:g id="PERCENTAGE">%s</xliff:g>"</string>
<string name="invalid_charger_title" msgid="938685362320735167">"Не може да се полни преку USB"</string>
<string name="invalid_charger_text" msgid="2339310107232691577">"Користете го полначот што дојде со вашиот уред"</string>
<string name="battery_saver_confirmation_title" msgid="1234998463717398453">"Да се вклучи „Штедачот на батерија“?"</string>
<string name="battery_saver_confirmation_title_generic" msgid="2299231884234959849">"За „Штедачот на батерија“"</string>
<string name="battery_saver_confirmation_ok" msgid="5042136476802816494">"Вклучи"</string>
- <string name="battery_saver_start_action" msgid="4553256017945469937">"Да се вклучи штедачот на батерија?"</string>
+ <string name="battery_saver_start_action" msgid="8353766979886287140">"Вклучи"</string>
+ <string name="battery_saver_dismiss_action" msgid="7199342621040014738">"Не, фала"</string>
<string name="status_bar_settings_auto_rotation" msgid="8329080442278431708">"Автоматско ротирање на екранот"</string>
<string name="usb_device_permission_prompt" msgid="4414719028369181772">"Ќе дозволите <xliff:g id="APPLICATION">%1$s</xliff:g> да пристапува до <xliff:g id="USB_DEVICE">%2$s</xliff:g>?"</string>
<string name="usb_device_permission_prompt_warn" msgid="2309129784984063656">"Дали дозволувате <xliff:g id="APPLICATION">%1$s</xliff:g> да пристапи до <xliff:g id="USB_DEVICE">%2$s</xliff:g>?\nНа апликацијава не ѝ е доделена дозвола за снимање, но може да снима аудио преку овој USB-уред."</string>
@@ -133,8 +131,7 @@
<string name="biometric_dialog_face_icon_description_authenticated" msgid="2242167416140740920">"Лицето е проверено"</string>
<string name="biometric_dialog_face_icon_description_confirmed" msgid="7918067993953940778">"Потврдено"</string>
<string name="biometric_dialog_tap_confirm" msgid="9166350738859143358">"Допрете „Потврди“ за да се заврши"</string>
- <!-- no translation found for biometric_dialog_tap_confirm_with_face (1597899891472340950) -->
- <skip />
+ <string name="biometric_dialog_tap_confirm_with_face" msgid="1597899891472340950">"Отклучен со вашето лице. Притиснете за да продолжите."</string>
<string name="biometric_dialog_authenticated" msgid="7337147327545272484">"Проверена"</string>
<string name="biometric_dialog_use_pin" msgid="8385294115283000709">"Користи PIN"</string>
<string name="biometric_dialog_use_pattern" msgid="2315593393167211194">"Користи шема"</string>
@@ -462,8 +459,8 @@
<string name="wallet_secondary_label_device_locked" msgid="5175862019125370506">"Отклучете за да користите"</string>
<string name="wallet_error_generic" msgid="257704570182963611">"Имаше проблем при преземањето на картичките. Обидете се повторно подоцна"</string>
<string name="wallet_lockscreen_settings_label" msgid="3539105300870383570">"Поставки за заклучен екран"</string>
- <string name="qr_code_scanner_title" msgid="5660820608548306581">"QR-код"</string>
- <string name="qr_code_scanner_description" msgid="7937603775306661863">"Допрете за скенирање"</string>
+ <!-- no translation found for qr_code_scanner_title (5290201053875420785) -->
+ <skip />
<string name="status_bar_work" msgid="5238641949837091056">"Работен профил"</string>
<string name="status_bar_airplane" msgid="4848702508684541009">"Авионски режим"</string>
<string name="zen_alarm_warning" msgid="7844303238486849503">"Нема да го слушнете следниот аларм <xliff:g id="WHEN">%1$s</xliff:g>"</string>
@@ -827,6 +824,7 @@
<string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"Спарете нов уред"</string>
<string name="media_output_dialog_launch_app_text" msgid="1527413319632586259">"За да ја емитувате сесијава, отворете ја апликацијата."</string>
<string name="media_output_dialog_unknown_launch_app_name" msgid="1084899329829371336">"Непозната апликација"</string>
+ <string name="media_output_dialog_button_stop_casting" msgid="6581379537930199189">"Сопри со емитување"</string>
<string name="build_number_clip_data_label" msgid="3623176728412560914">"Број на верзија"</string>
<string name="build_number_copy_toast" msgid="877720921605503046">"Бројот на верзијата е копиран во привремената меморија."</string>
<string name="basic_status" msgid="2315371112182658176">"Започни разговор"</string>
@@ -916,7 +914,6 @@
<string name="dream_overlay_status_bar_wifi_off" msgid="4497069245055003582">"Wi‑Fi е недостапна"</string>
<string name="dream_overlay_status_bar_priority_mode" msgid="5428462123314728739">"Приоритетен режим"</string>
<string name="dream_overlay_status_bar_alarm_set" msgid="566707328356590886">"Алармот е наместен"</string>
- <string name="dream_overlay_status_bar_assistant_guest_mode_enabled" msgid="3715897096012469615">"Режимот на гостин за „Помошникот“ е овозможен"</string>
<string name="dream_overlay_status_bar_camera_mic_off" msgid="3199425257833773569">"Камерата и микрофонот се исклучени"</string>
<string name="dream_overlay_status_bar_notification_indicator" msgid="8091389255691081711">"{count,plural, =1{# известување}one{# известување}other{# известувања}}"</string>
</resources>
diff --git a/packages/SystemUI/res/values-ml/strings.xml b/packages/SystemUI/res/values-ml/strings.xml
index 6aeb7e7..e7ccae0 100644
--- a/packages/SystemUI/res/values-ml/strings.xml
+++ b/packages/SystemUI/res/values-ml/strings.xml
@@ -20,19 +20,17 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_label" msgid="4811759950673118541">"സിസ്റ്റം UI"</string>
- <!-- no translation found for battery_low_title (5319680173344341779) -->
- <skip />
- <!-- no translation found for battery_low_description (3282977755476423966) -->
- <skip />
- <!-- no translation found for battery_low_intro (5148725009653088790) -->
- <skip />
+ <string name="battery_low_title" msgid="5319680173344341779">"ബാറ്ററി ലാഭിക്കൽ ഓണാക്കണോ?"</string>
+ <string name="battery_low_description" msgid="3282977755476423966">"നിങ്ങളുടെ ബാറ്ററിയിൽ <xliff:g id="PERCENTAGE">%s</xliff:g> ചാർജ് ശേഷിക്കുന്നു. ബാറ്ററി ലാഭിക്കൽ, ഡാർക്ക് തീം ഓണാക്കുകയും പശ്ചാത്തല ആക്റ്റിവിറ്റി നിയന്ത്രിക്കുകയും അറിയിപ്പുകൾ വെെകിപ്പിക്കുകയും ചെയ്യുന്നു."</string>
+ <string name="battery_low_intro" msgid="5148725009653088790">"ബാറ്ററി ലാഭിക്കൽ, ഡാർക്ക് തീം ഓണാക്കുകയും പശ്ചാത്തല ആക്റ്റിവിറ്റി നിയന്ത്രിക്കുകയും അറിയിപ്പുകൾ വെെകിപ്പിക്കുകയും ചെയ്യുന്നു."</string>
<string name="battery_low_percent_format" msgid="4276661262843170964">"<xliff:g id="PERCENTAGE">%s</xliff:g> ശേഷിക്കുന്നു"</string>
<string name="invalid_charger_title" msgid="938685362320735167">"USB വഴി ചാർജ് ചെയ്യാനാകില്ല"</string>
<string name="invalid_charger_text" msgid="2339310107232691577">"ഉപകരണത്തിനൊപ്പം ലഭിച്ച ചാർജർ ഉപയോഗിക്കുക"</string>
<string name="battery_saver_confirmation_title" msgid="1234998463717398453">"ബാറ്ററി ലാഭിക്കൽ ഓണാക്കണോ?"</string>
<string name="battery_saver_confirmation_title_generic" msgid="2299231884234959849">"ബാറ്ററി ലാഭിക്കലിനെ കുറിച്ച്"</string>
<string name="battery_saver_confirmation_ok" msgid="5042136476802816494">"ഓൺ ചെയ്യുക"</string>
- <string name="battery_saver_start_action" msgid="4553256017945469937">"ബാറ്ററി ലാഭിക്കൽ ഓണാക്കുക"</string>
+ <string name="battery_saver_start_action" msgid="8353766979886287140">"ഓണാക്കുക"</string>
+ <string name="battery_saver_dismiss_action" msgid="7199342621040014738">"വേണ്ട"</string>
<string name="status_bar_settings_auto_rotation" msgid="8329080442278431708">"സ്ക്രീൻ സ്വയമേ തിരിയുക"</string>
<string name="usb_device_permission_prompt" msgid="4414719028369181772">"<xliff:g id="USB_DEVICE">%2$s</xliff:g> ആക്സസ് ചെയ്യാൻ <xliff:g id="APPLICATION">%1$s</xliff:g>-നെ അനുവദിക്കണോ?"</string>
<string name="usb_device_permission_prompt_warn" msgid="2309129784984063656">"<xliff:g id="USB_DEVICE">%2$s</xliff:g> ആക്സസ് ചെയ്യാൻ <xliff:g id="APPLICATION">%1$s</xliff:g> എന്നതിനെ അനുവദിക്കണോ?\nഈ ആപ്പിന് റെക്കോർഡ് അനുമതി നൽകിയിട്ടില്ല, എന്നാൽ ഈ USB ഉപകരണത്തിലൂടെ ഓഡിയോ ക്യാപ്ചർ ചെയ്യാനാവും."</string>
@@ -133,8 +131,7 @@
<string name="biometric_dialog_face_icon_description_authenticated" msgid="2242167416140740920">"മുഖം പരിശോധിച്ചുറപ്പിച്ചു"</string>
<string name="biometric_dialog_face_icon_description_confirmed" msgid="7918067993953940778">"സ്ഥിരീകരിച്ചു"</string>
<string name="biometric_dialog_tap_confirm" msgid="9166350738859143358">"പൂർത്തിയാക്കാൻ സ്ഥിരീകരിക്കുക ടാപ്പ് ചെയ്യൂ"</string>
- <!-- no translation found for biometric_dialog_tap_confirm_with_face (1597899891472340950) -->
- <skip />
+ <string name="biometric_dialog_tap_confirm_with_face" msgid="1597899891472340950">"മുഖം ഉപയോഗിച്ച് അൺലോക്ക് ചെയ്തു. തുടരാൻ അമർത്തുക."</string>
<string name="biometric_dialog_authenticated" msgid="7337147327545272484">"പരിശോധിച്ചുറപ്പിച്ചു"</string>
<string name="biometric_dialog_use_pin" msgid="8385294115283000709">"പിൻ ഉപയോഗിക്കുക"</string>
<string name="biometric_dialog_use_pattern" msgid="2315593393167211194">"പാറ്റേൺ ഉപയോഗിക്കുക"</string>
@@ -462,8 +459,8 @@
<string name="wallet_secondary_label_device_locked" msgid="5175862019125370506">"ഉപയോഗിക്കാൻ അൺലോക്ക് ചെയ്യുക"</string>
<string name="wallet_error_generic" msgid="257704570182963611">"നിങ്ങളുടെ കാർഡുകൾ ലഭ്യമാക്കുന്നതിൽ ഒരു പ്രശ്നമുണ്ടായി, പിന്നീട് വീണ്ടും ശ്രമിക്കുക"</string>
<string name="wallet_lockscreen_settings_label" msgid="3539105300870383570">"ലോക്ക് സ്ക്രീൻ ക്രമീകരണം"</string>
- <string name="qr_code_scanner_title" msgid="5660820608548306581">"QR കോഡ്"</string>
- <string name="qr_code_scanner_description" msgid="7937603775306661863">"സ്കാൻ ചെയ്യാൻ ടാപ്പ് ചെയ്യുക"</string>
+ <!-- no translation found for qr_code_scanner_title (5290201053875420785) -->
+ <skip />
<string name="status_bar_work" msgid="5238641949837091056">"ഔദ്യോഗിക പ്രൊഫൈൽ"</string>
<string name="status_bar_airplane" msgid="4848702508684541009">"ഫ്ലൈറ്റ് മോഡ്"</string>
<string name="zen_alarm_warning" msgid="7844303238486849503">"<xliff:g id="WHEN">%1$s</xliff:g>-നുള്ള നിങ്ങളുടെ അടുത്ത അലാറം കേൾക്കില്ല"</string>
@@ -827,6 +824,7 @@
<string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"പുതിയ ഉപകരണവുമായി ജോടിയാക്കുക"</string>
<string name="media_output_dialog_launch_app_text" msgid="1527413319632586259">"ഈ സെഷൻ കാസ്റ്റ് ചെയ്യാൻ, ആപ്പ് തുറക്കുക."</string>
<string name="media_output_dialog_unknown_launch_app_name" msgid="1084899329829371336">"അജ്ഞാതമായ ആപ്പ്"</string>
+ <string name="media_output_dialog_button_stop_casting" msgid="6581379537930199189">"കാസ്റ്റ് ചെയ്യുന്നത് നിർത്തുക"</string>
<string name="build_number_clip_data_label" msgid="3623176728412560914">"ബിൽഡ് നമ്പർ"</string>
<string name="build_number_copy_toast" msgid="877720921605503046">"ക്ലിപ്പ്ബോർഡിലേക്ക് ബിൽഡ് നമ്പർ പകർത്തി."</string>
<string name="basic_status" msgid="2315371112182658176">"സംഭാഷണം തുറക്കുക"</string>
@@ -916,7 +914,6 @@
<string name="dream_overlay_status_bar_wifi_off" msgid="4497069245055003582">"വൈഫൈ ലഭ്യമല്ല"</string>
<string name="dream_overlay_status_bar_priority_mode" msgid="5428462123314728739">"മുൻഗണനാ മോഡ്"</string>
<string name="dream_overlay_status_bar_alarm_set" msgid="566707328356590886">"അലാറം സജ്ജീകരിച്ചു"</string>
- <string name="dream_overlay_status_bar_assistant_guest_mode_enabled" msgid="3715897096012469615">"സഹായി അതിഥി മോഡ് പ്രവർത്തനക്ഷമമാക്കി"</string>
<string name="dream_overlay_status_bar_camera_mic_off" msgid="3199425257833773569">"ക്യാമറയും മൈക്കും ഓഫാണ്"</string>
<string name="dream_overlay_status_bar_notification_indicator" msgid="8091389255691081711">"{count,plural, =1{# അറിയിപ്പ്}other{# അറിയിപ്പുകൾ}}"</string>
</resources>
diff --git a/packages/SystemUI/res/values-mn/strings.xml b/packages/SystemUI/res/values-mn/strings.xml
index 4abfe1b..b136674 100644
--- a/packages/SystemUI/res/values-mn/strings.xml
+++ b/packages/SystemUI/res/values-mn/strings.xml
@@ -20,19 +20,17 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_label" msgid="4811759950673118541">"Систем UI"</string>
- <!-- no translation found for battery_low_title (5319680173344341779) -->
- <skip />
- <!-- no translation found for battery_low_description (3282977755476423966) -->
- <skip />
- <!-- no translation found for battery_low_intro (5148725009653088790) -->
- <skip />
+ <string name="battery_low_title" msgid="5319680173344341779">"Батарей хэмнэгчийг асаах уу?"</string>
+ <string name="battery_low_description" msgid="3282977755476423966">"Танд <xliff:g id="PERCENTAGE">%s</xliff:g> батарей үлдсэн байна. Батарей хэмнэгч нь Бараан загварыг асааж, дэвсгэрийн үйл ажиллагааг хязгаарлаж мөн мэдэгдлийг саатуулна."</string>
+ <string name="battery_low_intro" msgid="5148725009653088790">"Батарей хэмнэгч нь Бараан загварыг асааж, дэвсгэрийн үйл ажиллагааг хязгаарлаж мөн мэдэгдлийг саатуулна."</string>
<string name="battery_low_percent_format" msgid="4276661262843170964">"<xliff:g id="PERCENTAGE">%s</xliff:g> үлдсэн"</string>
<string name="invalid_charger_title" msgid="938685362320735167">"USB-р цэнэглэх боломжгүй байна"</string>
<string name="invalid_charger_text" msgid="2339310107232691577">"Төхөөрөмждөө дагалдаж ирсэн цэнэглэгчийг ашиглах"</string>
<string name="battery_saver_confirmation_title" msgid="1234998463717398453">"Батарей хэмнэгчийг асаах уу?"</string>
<string name="battery_saver_confirmation_title_generic" msgid="2299231884234959849">"Батарей хэмнэгчийн тухай"</string>
<string name="battery_saver_confirmation_ok" msgid="5042136476802816494">"Асаах"</string>
- <string name="battery_saver_start_action" msgid="4553256017945469937">"Батарей хэмнэгчийг асаах"</string>
+ <string name="battery_saver_start_action" msgid="8353766979886287140">"Асаах"</string>
+ <string name="battery_saver_dismiss_action" msgid="7199342621040014738">"Үгүй, баярлалаа"</string>
<string name="status_bar_settings_auto_rotation" msgid="8329080442278431708">"Дэлгэцийг автоматаар эргүүлэх"</string>
<string name="usb_device_permission_prompt" msgid="4414719028369181772">"<xliff:g id="APPLICATION">%1$s</xliff:g>-г <xliff:g id="USB_DEVICE">%2$s</xliff:g>-д хандахыг зөвшөөрөх үү?"</string>
<string name="usb_device_permission_prompt_warn" msgid="2309129784984063656">"<xliff:g id="APPLICATION">%1$s</xliff:g>-д <xliff:g id="USB_DEVICE">%2$s</xliff:g>-д хандахыг зөвшөөрөх үү?\nЭнэ аппад бичих зөвшөөрөл олгогдоогүй ч USB төхөөрөмжөөр дамжуулан аудио бичиж чадсан."</string>
@@ -133,8 +131,7 @@
<string name="biometric_dialog_face_icon_description_authenticated" msgid="2242167416140740920">"Царайг баталгаажууллаа"</string>
<string name="biometric_dialog_face_icon_description_confirmed" msgid="7918067993953940778">"Баталгаажсан"</string>
<string name="biometric_dialog_tap_confirm" msgid="9166350738859143358">"Дуусгахын тулд баталгаажуулахыг товших"</string>
- <!-- no translation found for biometric_dialog_tap_confirm_with_face (1597899891472340950) -->
- <skip />
+ <string name="biometric_dialog_tap_confirm_with_face" msgid="1597899891472340950">"Таны царайгаар түгжээг тайлсан. Үргэлжлүүлэхийн тулд дарна уу."</string>
<string name="biometric_dialog_authenticated" msgid="7337147327545272484">"Баталгаажуулагдсан"</string>
<string name="biometric_dialog_use_pin" msgid="8385294115283000709">"ПИН ашиглах"</string>
<string name="biometric_dialog_use_pattern" msgid="2315593393167211194">"Хээ ашиглах"</string>
@@ -462,8 +459,7 @@
<string name="wallet_secondary_label_device_locked" msgid="5175862019125370506">"Ашиглахын тулд түгжээг тайлах"</string>
<string name="wallet_error_generic" msgid="257704570182963611">"Таны картыг авахад асуудал гарлаа. Дараа дахин оролдоно уу"</string>
<string name="wallet_lockscreen_settings_label" msgid="3539105300870383570">"Түгжигдсэн дэлгэцийн тохиргоо"</string>
- <string name="qr_code_scanner_title" msgid="5660820608548306581">"QR код"</string>
- <string name="qr_code_scanner_description" msgid="7937603775306661863">"Скан хийхийн тулд товшино уу"</string>
+ <string name="qr_code_scanner_title" msgid="5290201053875420785">"QR код скан хийх"</string>
<string name="status_bar_work" msgid="5238641949837091056">"Ажлын профайл"</string>
<string name="status_bar_airplane" msgid="4848702508684541009">"Нислэгийн горим"</string>
<string name="zen_alarm_warning" msgid="7844303238486849503">"<xliff:g id="WHEN">%1$s</xliff:g>-т та дараагийн сэрүүлгээ сонсохгүй"</string>
@@ -827,6 +823,7 @@
<string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"Шинэ төхөөрөмж хослуулах"</string>
<string name="media_output_dialog_launch_app_text" msgid="1527413319632586259">"Энэ үйл явдлыг дамжуулахын тулд аппыг нээнэ үү."</string>
<string name="media_output_dialog_unknown_launch_app_name" msgid="1084899329829371336">"Үл мэдэгдэх апп"</string>
+ <string name="media_output_dialog_button_stop_casting" msgid="6581379537930199189">"Дамжуулахыг зогсоох"</string>
<string name="build_number_clip_data_label" msgid="3623176728412560914">"Хийцийн дугаар"</string>
<string name="build_number_copy_toast" msgid="877720921605503046">"Хийцийн дугаарыг түр санах ойд хуулсан."</string>
<string name="basic_status" msgid="2315371112182658176">"Харилцан яриаг нээх"</string>
@@ -916,7 +913,6 @@
<string name="dream_overlay_status_bar_wifi_off" msgid="4497069245055003582">"Wi‑Fi боломжгүй"</string>
<string name="dream_overlay_status_bar_priority_mode" msgid="5428462123314728739">"Чухал горим"</string>
<string name="dream_overlay_status_bar_alarm_set" msgid="566707328356590886">"Сэрүүлгийг тохируулсан"</string>
- <string name="dream_overlay_status_bar_assistant_guest_mode_enabled" msgid="3715897096012469615">"Туслахын зочны горимыг идэвхжүүлсэн"</string>
<string name="dream_overlay_status_bar_camera_mic_off" msgid="3199425257833773569">"Камер болон микрофон унтраалттай байна"</string>
<string name="dream_overlay_status_bar_notification_indicator" msgid="8091389255691081711">"{count,plural, =1{# мэдэгдэл}other{# мэдэгдэл}}"</string>
</resources>
diff --git a/packages/SystemUI/res/values-mr/strings.xml b/packages/SystemUI/res/values-mr/strings.xml
index 2ec0073..721368a 100644
--- a/packages/SystemUI/res/values-mr/strings.xml
+++ b/packages/SystemUI/res/values-mr/strings.xml
@@ -20,19 +20,17 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_label" msgid="4811759950673118541">"सिस्टीम UI"</string>
- <!-- no translation found for battery_low_title (5319680173344341779) -->
- <skip />
- <!-- no translation found for battery_low_description (3282977755476423966) -->
- <skip />
- <!-- no translation found for battery_low_intro (5148725009653088790) -->
- <skip />
+ <string name="battery_low_title" msgid="5319680173344341779">"बॅटरी सेव्हर सुरू करायचे आहे का?"</string>
+ <string name="battery_low_description" msgid="3282977755476423966">"तुमच्याकडे <xliff:g id="PERCENTAGE">%s</xliff:g> बॅटरी शिल्लक आहे. बॅटरी सेव्हर गडद थीम सुरू करते, बॅकग्राउंड ॲक्टिव्हिटी मर्यादित करते, यामुळे सूचना विलंबाने मिळतात."</string>
+ <string name="battery_low_intro" msgid="5148725009653088790">"बॅटरी सेव्हर गडद थीम सुरू करते, बॅकग्राउंड ॲक्टिव्हिटी मर्यादित करते, यामुळे सूचना विलंबाने मिळतात."</string>
<string name="battery_low_percent_format" msgid="4276661262843170964">"<xliff:g id="PERCENTAGE">%s</xliff:g> शिल्लक"</string>
<string name="invalid_charger_title" msgid="938685362320735167">"USB द्वारे चार्ज होऊ शकत नाही"</string>
<string name="invalid_charger_text" msgid="2339310107232691577">"तुमच्या डिव्हाइससह आलेल्या चार्जरचा वापर करा"</string>
<string name="battery_saver_confirmation_title" msgid="1234998463717398453">"बॅटरी सेव्हर सुरू करायचा का?"</string>
<string name="battery_saver_confirmation_title_generic" msgid="2299231884234959849">"बॅटरी सेव्हर बाबत"</string>
<string name="battery_saver_confirmation_ok" msgid="5042136476802816494">"सुरू करा"</string>
- <string name="battery_saver_start_action" msgid="4553256017945469937">"बॅटरी सेव्हर सुरू करा"</string>
+ <string name="battery_saver_start_action" msgid="8353766979886287140">"सुरू करा"</string>
+ <string name="battery_saver_dismiss_action" msgid="7199342621040014738">"नाही, नको"</string>
<string name="status_bar_settings_auto_rotation" msgid="8329080442278431708">"ऑटो-रोटेट स्क्रीन"</string>
<string name="usb_device_permission_prompt" msgid="4414719028369181772">"<xliff:g id="APPLICATION">%1$s</xliff:g> ला <xliff:g id="USB_DEVICE">%2$s</xliff:g> अॅक्सेस करण्याची अनुमती द्यायची का?"</string>
<string name="usb_device_permission_prompt_warn" msgid="2309129784984063656">"<xliff:g id="APPLICATION">%1$s</xliff:g> ला <xliff:g id="USB_DEVICE">%2$s</xliff:g> अॅक्सेस करण्याची अनुमती द्यायची का?\nया अॅपला रेकॉर्ड करण्याची परवानगी दिलेली नाही पण या USB डिव्हाइसद्वारे ऑडिओ कॅप्चर केला जाऊ शकतो."</string>
@@ -133,8 +131,7 @@
<string name="biometric_dialog_face_icon_description_authenticated" msgid="2242167416140740920">"चेहरा ऑथेंटिकेशन केलेला आहे"</string>
<string name="biometric_dialog_face_icon_description_confirmed" msgid="7918067993953940778">"निश्चित केले"</string>
<string name="biometric_dialog_tap_confirm" msgid="9166350738859143358">"पूर्ण करण्यासाठी खात्री करा वर टॅप करा"</string>
- <!-- no translation found for biometric_dialog_tap_confirm_with_face (1597899891472340950) -->
- <skip />
+ <string name="biometric_dialog_tap_confirm_with_face" msgid="1597899891472340950">"तुमच्या चेहऱ्याने अनलॉक केले. पुढे सुरू ठेवण्यासाठी दाबा."</string>
<string name="biometric_dialog_authenticated" msgid="7337147327545272484">"ऑथेंटिकेशन केलेले"</string>
<string name="biometric_dialog_use_pin" msgid="8385294115283000709">"पिन वापरा"</string>
<string name="biometric_dialog_use_pattern" msgid="2315593393167211194">"पॅटर्न वापरा"</string>
@@ -462,8 +459,8 @@
<string name="wallet_secondary_label_device_locked" msgid="5175862019125370506">"वापरण्यासाठी अनलॉक करा"</string>
<string name="wallet_error_generic" msgid="257704570182963611">"तुमची कार्ड मिळवताना समस्या आली, कृपया नंतर पुन्हा प्रयत्न करा"</string>
<string name="wallet_lockscreen_settings_label" msgid="3539105300870383570">"लॉक स्क्रीन सेटिंग्ज"</string>
- <string name="qr_code_scanner_title" msgid="5660820608548306581">"QR कोड"</string>
- <string name="qr_code_scanner_description" msgid="7937603775306661863">"स्कॅन करण्यासाठी टॅप करा"</string>
+ <!-- no translation found for qr_code_scanner_title (5290201053875420785) -->
+ <skip />
<string name="status_bar_work" msgid="5238641949837091056">"कार्य प्रोफाईल"</string>
<string name="status_bar_airplane" msgid="4848702508684541009">"विमान मोड"</string>
<string name="zen_alarm_warning" msgid="7844303238486849503">"तुम्ही तुमचा <xliff:g id="WHEN">%1$s</xliff:g> वाजता होणारा पुढील अलार्म ऐकणार नाही"</string>
@@ -827,6 +824,7 @@
<string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"नवीन डिव्हाइससोबत पेअर करा"</string>
<string name="media_output_dialog_launch_app_text" msgid="1527413319632586259">"हे सेशन कास्ट करण्यासाठी, कृपया ॲप उघडा."</string>
<string name="media_output_dialog_unknown_launch_app_name" msgid="1084899329829371336">"अज्ञात अॅप"</string>
+ <string name="media_output_dialog_button_stop_casting" msgid="6581379537930199189">"कास्ट करणे थांबवा"</string>
<string name="build_number_clip_data_label" msgid="3623176728412560914">"बिल्ड नंबर"</string>
<string name="build_number_copy_toast" msgid="877720921605503046">"बिल्ड नंबर क्लिपबोर्डवर कॉपी केला."</string>
<string name="basic_status" msgid="2315371112182658176">"संभाषण उघडा"</string>
@@ -916,7 +914,6 @@
<string name="dream_overlay_status_bar_wifi_off" msgid="4497069245055003582">"वाय-फाय उपलब्ध नाही"</string>
<string name="dream_overlay_status_bar_priority_mode" msgid="5428462123314728739">"प्राधान्य मोड"</string>
<string name="dream_overlay_status_bar_alarm_set" msgid="566707328356590886">"अलार्म सेट केला"</string>
- <string name="dream_overlay_status_bar_assistant_guest_mode_enabled" msgid="3715897096012469615">"Assistant चा अतिथी मोड सुरू केला"</string>
<string name="dream_overlay_status_bar_camera_mic_off" msgid="3199425257833773569">"कॅमेरा आणि माइक बंद आहेत"</string>
<string name="dream_overlay_status_bar_notification_indicator" msgid="8091389255691081711">"{count,plural, =1{# सूचना}other{# सूचना}}"</string>
</resources>
diff --git a/packages/SystemUI/res/values-ms/strings.xml b/packages/SystemUI/res/values-ms/strings.xml
index 06270d7..b34a312 100644
--- a/packages/SystemUI/res/values-ms/strings.xml
+++ b/packages/SystemUI/res/values-ms/strings.xml
@@ -20,19 +20,17 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_label" msgid="4811759950673118541">"UI Sistem"</string>
- <!-- no translation found for battery_low_title (5319680173344341779) -->
- <skip />
- <!-- no translation found for battery_low_description (3282977755476423966) -->
- <skip />
- <!-- no translation found for battery_low_intro (5148725009653088790) -->
- <skip />
+ <string name="battery_low_title" msgid="5319680173344341779">"Hidupkan Penjimat Bateri?"</string>
+ <string name="battery_low_description" msgid="3282977755476423966">"Anda mempunyai <xliff:g id="PERCENTAGE">%s</xliff:g> baki bateri. Penjimat Bateri menghidupkan Tema gelap, mengehadkan aktiviti latar dan menangguhkan pemberitahuan."</string>
+ <string name="battery_low_intro" msgid="5148725009653088790">"Penjimat Bateri menghidupkan Tema gelap, mengehadkan aktiviti latar dan menangguhkan pemberitahuan."</string>
<string name="battery_low_percent_format" msgid="4276661262843170964">"<xliff:g id="PERCENTAGE">%s</xliff:g> yang tinggal"</string>
<string name="invalid_charger_title" msgid="938685362320735167">"Tidak dapat mengecas melalui USB"</string>
<string name="invalid_charger_text" msgid="2339310107232691577">"Gunakan pengecas yang disertakan dengan peranti anda"</string>
<string name="battery_saver_confirmation_title" msgid="1234998463717398453">"Hidupkan Penjimat Bateri?"</string>
<string name="battery_saver_confirmation_title_generic" msgid="2299231884234959849">"Tentang Penjimat Bateri"</string>
<string name="battery_saver_confirmation_ok" msgid="5042136476802816494">"Hidupkan"</string>
- <string name="battery_saver_start_action" msgid="4553256017945469937">"Hidupkan Penjimat Bateri"</string>
+ <string name="battery_saver_start_action" msgid="8353766979886287140">"Hidupkan"</string>
+ <string name="battery_saver_dismiss_action" msgid="7199342621040014738">"Tidak perlu"</string>
<string name="status_bar_settings_auto_rotation" msgid="8329080442278431708">"Autoputar skrin"</string>
<string name="usb_device_permission_prompt" msgid="4414719028369181772">"Benarkan <xliff:g id="APPLICATION">%1$s</xliff:g> mengakses <xliff:g id="USB_DEVICE">%2$s</xliff:g>?"</string>
<string name="usb_device_permission_prompt_warn" msgid="2309129784984063656">"Benarkan <xliff:g id="APPLICATION">%1$s</xliff:g> mengakses <xliff:g id="USB_DEVICE">%2$s</xliff:g>?\nApl ini belum diberikan kebenaran merakam tetapi dapat merakam audio melalui peranti USB ini."</string>
@@ -133,8 +131,7 @@
<string name="biometric_dialog_face_icon_description_authenticated" msgid="2242167416140740920">"Wajah disahkan"</string>
<string name="biometric_dialog_face_icon_description_confirmed" msgid="7918067993953940778">"Disahkan"</string>
<string name="biometric_dialog_tap_confirm" msgid="9166350738859143358">"Ketik Sahkan untuk menyelesaikan"</string>
- <!-- no translation found for biometric_dialog_tap_confirm_with_face (1597899891472340950) -->
- <skip />
+ <string name="biometric_dialog_tap_confirm_with_face" msgid="1597899891472340950">"Dibuka kunci oleh wajah anda. Tekan untuk meneruskan."</string>
<string name="biometric_dialog_authenticated" msgid="7337147327545272484">"Disahkan"</string>
<string name="biometric_dialog_use_pin" msgid="8385294115283000709">"Gunakan PIN"</string>
<string name="biometric_dialog_use_pattern" msgid="2315593393167211194">"Gunakan corak"</string>
@@ -462,8 +459,8 @@
<string name="wallet_secondary_label_device_locked" msgid="5175862019125370506">"Buka kunci untuk menggunakan"</string>
<string name="wallet_error_generic" msgid="257704570182963611">"Terdapat masalah sewaktu mendapatkan kad anda. Sila cuba sebentar lagi"</string>
<string name="wallet_lockscreen_settings_label" msgid="3539105300870383570">"Tetapan skrin kunci"</string>
- <string name="qr_code_scanner_title" msgid="5660820608548306581">"Kod QR"</string>
- <string name="qr_code_scanner_description" msgid="7937603775306661863">"Ketik untuk membuat imbasan"</string>
+ <!-- no translation found for qr_code_scanner_title (5290201053875420785) -->
+ <skip />
<string name="status_bar_work" msgid="5238641949837091056">"Profil kerja"</string>
<string name="status_bar_airplane" msgid="4848702508684541009">"Mod pesawat"</string>
<string name="zen_alarm_warning" msgid="7844303238486849503">"Anda tidak akan mendengar penggera yang seterusnya <xliff:g id="WHEN">%1$s</xliff:g>"</string>
@@ -827,6 +824,7 @@
<string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"Gandingkan peranti baharu"</string>
<string name="media_output_dialog_launch_app_text" msgid="1527413319632586259">"Untuk menghantar sesi ini, sila buka apl."</string>
<string name="media_output_dialog_unknown_launch_app_name" msgid="1084899329829371336">"Apl yang tidak diketahui"</string>
+ <string name="media_output_dialog_button_stop_casting" msgid="6581379537930199189">"Berhenti menghantar"</string>
<string name="build_number_clip_data_label" msgid="3623176728412560914">"Nombor binaan"</string>
<string name="build_number_copy_toast" msgid="877720921605503046">"Nombor binaan disalin ke papan keratan."</string>
<string name="basic_status" msgid="2315371112182658176">"Buka perbualan"</string>
@@ -916,8 +914,6 @@
<string name="dream_overlay_status_bar_wifi_off" msgid="4497069245055003582">"Wi‑Fi dimatikan"</string>
<string name="dream_overlay_status_bar_priority_mode" msgid="5428462123314728739">"Mod keutamaan"</string>
<string name="dream_overlay_status_bar_alarm_set" msgid="566707328356590886">"Penggera ditetapkan"</string>
- <string name="dream_overlay_status_bar_assistant_guest_mode_enabled" msgid="3715897096012469615">"Mod tetamu Assistant didayakan"</string>
<string name="dream_overlay_status_bar_camera_mic_off" msgid="3199425257833773569">"Kamera dan mikrofon dimatikan"</string>
- <!-- no translation found for dream_overlay_status_bar_notification_indicator (8091389255691081711) -->
- <skip />
+ <string name="dream_overlay_status_bar_notification_indicator" msgid="8091389255691081711">"{count,plural, =1{# pemberitahuan}other{# pemberitahuan}}"</string>
</resources>
diff --git a/packages/SystemUI/res/values-my/strings.xml b/packages/SystemUI/res/values-my/strings.xml
index 4a4f1a1..b1b2ceb 100644
--- a/packages/SystemUI/res/values-my/strings.xml
+++ b/packages/SystemUI/res/values-my/strings.xml
@@ -20,19 +20,17 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_label" msgid="4811759950673118541">"စနစ်၏ UI"</string>
- <!-- no translation found for battery_low_title (5319680173344341779) -->
- <skip />
- <!-- no translation found for battery_low_description (3282977755476423966) -->
- <skip />
- <!-- no translation found for battery_low_intro (5148725009653088790) -->
- <skip />
+ <string name="battery_low_title" msgid="5319680173344341779">"‘ဘက်ထရီ အားထိန်း’ ဖွင့်မလား။"</string>
+ <string name="battery_low_description" msgid="3282977755476423966">"သင့်တွင် ဘက်ထရီ <xliff:g id="PERCENTAGE">%s</xliff:g> ကျန်သည်။ ‘ဘက်ထရီ အားထိန်း’ က ‘မှောင်သည့် အပြင်အဆင်’ ဖွင့်ပြီး နောက်ခံလုပ်ဆောင်ချက်ကို ကန့်သတ်ကာ အကြောင်းကြားချက်များကို နှောင့်နှေးစေသည်။"</string>
+ <string name="battery_low_intro" msgid="5148725009653088790">"‘ဘက်ထရီ အားထိန်း’ က ‘မှောင်သည့် အပြင်အဆင်’ ဖွင့်ပြီး နောက်ခံလုပ်ဆောင်ချက်ကို ကန့်သတ်ကာ အကြောင်းကြားချက်များကို နှောင့်နှေးစေသည်။"</string>
<string name="battery_low_percent_format" msgid="4276661262843170964">"<xliff:g id="PERCENTAGE">%s</xliff:g> ကျန်ရှိနေ"</string>
<string name="invalid_charger_title" msgid="938685362320735167">"USB ဖြင့် အားသွင်း၍မရပါ"</string>
<string name="invalid_charger_text" msgid="2339310107232691577">"သင့်စက်ပစ္စည်းနှင့် အတူပါလာသည့် အားသွင်းကိရိယာကို အသုံးပြုပါ"</string>
<string name="battery_saver_confirmation_title" msgid="1234998463717398453">"ဘက်ထရီအားထိန်းကို ဖွင့်မလား။"</string>
<string name="battery_saver_confirmation_title_generic" msgid="2299231884234959849">"\'ဘက်ထရီအားထိန်း\' အကြောင်း"</string>
<string name="battery_saver_confirmation_ok" msgid="5042136476802816494">"ဖွင့်ရန်"</string>
- <string name="battery_saver_start_action" msgid="4553256017945469937">"ဘက်ထရီ အားထိန်းကို ဖွင့်ရန်"</string>
+ <string name="battery_saver_start_action" msgid="8353766979886287140">"ဖွင့်ရန်"</string>
+ <string name="battery_saver_dismiss_action" msgid="7199342621040014738">"မလိုပါ"</string>
<string name="status_bar_settings_auto_rotation" msgid="8329080442278431708">"ဖန်သားပြင် အလိုအလျောက်လှည့်ရန်"</string>
<string name="usb_device_permission_prompt" msgid="4414719028369181772">"<xliff:g id="USB_DEVICE">%2$s</xliff:g> အား ဝင်သုံးရန် <xliff:g id="APPLICATION">%1$s</xliff:g> ကို ခွင့်ပြုပါသလား။"</string>
<string name="usb_device_permission_prompt_warn" msgid="2309129784984063656">"<xliff:g id="APPLICATION">%1$s</xliff:g> အား <xliff:g id="USB_DEVICE">%2$s</xliff:g> ကို သုံးခွင့်ပြုမလား။\nဤအက်ပ်ကို အသံဖမ်းခွင့် ပေးမထားသော်လည်း ၎င်းသည် ဤ USB စက်ပစ္စည်းမှတစ်ဆင့် အသံများကို ဖမ်းယူနိုင်ပါသည်။"</string>
@@ -133,8 +131,7 @@
<string name="biometric_dialog_face_icon_description_authenticated" msgid="2242167416140740920">"မျက်နှာ အထောက်အထားစိစစ်ပြီးပြီ"</string>
<string name="biometric_dialog_face_icon_description_confirmed" msgid="7918067993953940778">"အတည်ပြုပြီးပြီ"</string>
<string name="biometric_dialog_tap_confirm" msgid="9166350738859143358">"အပြီးသတ်ရန်အတွက် \'အတည်ပြုရန်\' ကို တို့ပါ"</string>
- <!-- no translation found for biometric_dialog_tap_confirm_with_face (1597899891472340950) -->
- <skip />
+ <string name="biometric_dialog_tap_confirm_with_face" msgid="1597899891472340950">"သင့်မျက်နှာဖြင့် ဖွင့်သည်။ ရှေ့ဆက်ရန် နှိပ်ပါ။"</string>
<string name="biometric_dialog_authenticated" msgid="7337147327545272484">"အထောက်အထားစိစစ်ပြီးပြီ"</string>
<string name="biometric_dialog_use_pin" msgid="8385294115283000709">"ပင်နံပါတ်သုံးရန်"</string>
<string name="biometric_dialog_use_pattern" msgid="2315593393167211194">"ပုံစံကို သုံးရန်"</string>
@@ -462,8 +459,8 @@
<string name="wallet_secondary_label_device_locked" msgid="5175862019125370506">"သုံးရန် လော့ခ်ဖွင့်ပါ"</string>
<string name="wallet_error_generic" msgid="257704570182963611">"သင်၏ကတ်များ ရယူရာတွင် ပြဿနာရှိနေသည်၊ နောက်မှ ထပ်စမ်းကြည့်ပါ"</string>
<string name="wallet_lockscreen_settings_label" msgid="3539105300870383570">"လော့ခ်မျက်နှာပြင် ဆက်တင်များ"</string>
- <string name="qr_code_scanner_title" msgid="5660820608548306581">"QR ကုဒ်"</string>
- <string name="qr_code_scanner_description" msgid="7937603775306661863">"စကင်ဖတ်ရန် တို့နိုင်သည်"</string>
+ <!-- no translation found for qr_code_scanner_title (5290201053875420785) -->
+ <skip />
<string name="status_bar_work" msgid="5238641949837091056">"အလုပ် ပရိုဖိုင်"</string>
<string name="status_bar_airplane" msgid="4848702508684541009">"လေယာဉ်ပျံမုဒ်"</string>
<string name="zen_alarm_warning" msgid="7844303238486849503">"<xliff:g id="WHEN">%1$s</xliff:g> ၌သင့်နောက်ထပ် နှိုးစက်ကို ကြားမည်မဟုတ်ပါ"</string>
@@ -827,6 +824,7 @@
<string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"စက်အသစ် တွဲချိတ်ရန်"</string>
<string name="media_output_dialog_launch_app_text" msgid="1527413319632586259">"အက်ပ်ဖွင့်ပြီး ဤစက်ရှင်ကို ကာစ်လုပ်နိုင်သည်။"</string>
<string name="media_output_dialog_unknown_launch_app_name" msgid="1084899329829371336">"အမည်မသိ အက်ပ်"</string>
+ <string name="media_output_dialog_button_stop_casting" msgid="6581379537930199189">"ကာစ် ရပ်ရန်"</string>
<string name="build_number_clip_data_label" msgid="3623176728412560914">"တည်ဆောက်မှုနံပါတ်"</string>
<string name="build_number_copy_toast" msgid="877720921605503046">"တည်ဆောက်မှုနံပါတ်ကို ကလစ်ဘုတ်သို့ မိတ္တူကူးပြီးပါပြီ။"</string>
<string name="basic_status" msgid="2315371112182658176">"စကားဝိုင်းကို ဖွင့်ရန်"</string>
@@ -916,8 +914,6 @@
<string name="dream_overlay_status_bar_wifi_off" msgid="4497069245055003582">"Wi‑Fi မရပါ"</string>
<string name="dream_overlay_status_bar_priority_mode" msgid="5428462123314728739">"ဦးစားပေးမုဒ်"</string>
<string name="dream_overlay_status_bar_alarm_set" msgid="566707328356590886">"နိုးစက် သတ်မှတ်ထားသည်"</string>
- <string name="dream_overlay_status_bar_assistant_guest_mode_enabled" msgid="3715897096012469615">"Assistant ဧည့်သည်သုံးခွင့်မုဒ် ဖွင့်ထားသည်"</string>
<string name="dream_overlay_status_bar_camera_mic_off" msgid="3199425257833773569">"ကင်မရာနှင့် မိုက် ပိတ်ထားသည်"</string>
- <!-- no translation found for dream_overlay_status_bar_notification_indicator (8091389255691081711) -->
- <skip />
+ <string name="dream_overlay_status_bar_notification_indicator" msgid="8091389255691081711">"{count,plural, =1{အကြောင်းကြားချက် # ခု}other{အကြောင်းကြားချက် # ခု}}"</string>
</resources>
diff --git a/packages/SystemUI/res/values-nb/strings.xml b/packages/SystemUI/res/values-nb/strings.xml
index 5ccf528..745454c 100644
--- a/packages/SystemUI/res/values-nb/strings.xml
+++ b/packages/SystemUI/res/values-nb/strings.xml
@@ -20,19 +20,17 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_label" msgid="4811759950673118541">"System-UI"</string>
- <!-- no translation found for battery_low_title (5319680173344341779) -->
- <skip />
- <!-- no translation found for battery_low_description (3282977755476423966) -->
- <skip />
- <!-- no translation found for battery_low_intro (5148725009653088790) -->
- <skip />
+ <string name="battery_low_title" msgid="5319680173344341779">"Vil du slå på batterisparing?"</string>
+ <string name="battery_low_description" msgid="3282977755476423966">"Du har <xliff:g id="PERCENTAGE">%s</xliff:g> batteri igjen. Batterisparing slår på mørkt tema, begrenser bakgrunnsaktivitet og forsinker varsler."</string>
+ <string name="battery_low_intro" msgid="5148725009653088790">"Batterisparing slår på mørkt tema, begrenser bakgrunnsaktivitet og forsinker varsler."</string>
<string name="battery_low_percent_format" msgid="4276661262843170964">"<xliff:g id="PERCENTAGE">%s</xliff:g> gjenstår"</string>
<string name="invalid_charger_title" msgid="938685362320735167">"Kan ikke lade via USB"</string>
<string name="invalid_charger_text" msgid="2339310107232691577">"Bruk laderen som fulgte med enheten"</string>
<string name="battery_saver_confirmation_title" msgid="1234998463717398453">"Vil du slå på batterisparing?"</string>
<string name="battery_saver_confirmation_title_generic" msgid="2299231884234959849">"Om Batterisparing"</string>
<string name="battery_saver_confirmation_ok" msgid="5042136476802816494">"Slå på"</string>
- <string name="battery_saver_start_action" msgid="4553256017945469937">"Slå på batterisparing"</string>
+ <string name="battery_saver_start_action" msgid="8353766979886287140">"Slå på"</string>
+ <string name="battery_saver_dismiss_action" msgid="7199342621040014738">"Nei takk"</string>
<string name="status_bar_settings_auto_rotation" msgid="8329080442278431708">"Rotér skjermen automatisk"</string>
<string name="usb_device_permission_prompt" msgid="4414719028369181772">"Vil du gi <xliff:g id="APPLICATION">%1$s</xliff:g> tilgang til <xliff:g id="USB_DEVICE">%2$s</xliff:g>?"</string>
<string name="usb_device_permission_prompt_warn" msgid="2309129784984063656">"Vil du gi <xliff:g id="APPLICATION">%1$s</xliff:g> tilgang til <xliff:g id="USB_DEVICE">%2$s</xliff:g>?\nDenne appen har ikke fått tillatelse til å spille inn, men kan ta opp lyd med denne USB-enheten."</string>
@@ -133,8 +131,7 @@
<string name="biometric_dialog_face_icon_description_authenticated" msgid="2242167416140740920">"Ansiktet er autentisert"</string>
<string name="biometric_dialog_face_icon_description_confirmed" msgid="7918067993953940778">"Bekreftet"</string>
<string name="biometric_dialog_tap_confirm" msgid="9166350738859143358">"Trykk på Bekreft for å fullføre"</string>
- <!-- no translation found for biometric_dialog_tap_confirm_with_face (1597899891472340950) -->
- <skip />
+ <string name="biometric_dialog_tap_confirm_with_face" msgid="1597899891472340950">"Låst opp med ansiktet ditt. Trykk for å fortsette."</string>
<string name="biometric_dialog_authenticated" msgid="7337147327545272484">"Autentisert"</string>
<string name="biometric_dialog_use_pin" msgid="8385294115283000709">"Bruk PIN-kode"</string>
<string name="biometric_dialog_use_pattern" msgid="2315593393167211194">"Bruk mønster"</string>
@@ -462,8 +459,8 @@
<string name="wallet_secondary_label_device_locked" msgid="5175862019125370506">"Lås opp for å bruke"</string>
<string name="wallet_error_generic" msgid="257704570182963611">"Det oppsto et problem med henting av kortene. Prøv igjen senere"</string>
<string name="wallet_lockscreen_settings_label" msgid="3539105300870383570">"Innstillinger for låseskjermen"</string>
- <string name="qr_code_scanner_title" msgid="5660820608548306581">"QR-kode"</string>
- <string name="qr_code_scanner_description" msgid="7937603775306661863">"Trykk for å skanne"</string>
+ <!-- no translation found for qr_code_scanner_title (5290201053875420785) -->
+ <skip />
<string name="status_bar_work" msgid="5238641949837091056">"Work-profil"</string>
<string name="status_bar_airplane" msgid="4848702508684541009">"Flymodus"</string>
<string name="zen_alarm_warning" msgid="7844303238486849503">"Du hører ikke neste innstilte alarm <xliff:g id="WHEN">%1$s</xliff:g>"</string>
@@ -827,6 +824,7 @@
<string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"Koble til en ny enhet"</string>
<string name="media_output_dialog_launch_app_text" msgid="1527413319632586259">"For å caste denne økten, åpne appen."</string>
<string name="media_output_dialog_unknown_launch_app_name" msgid="1084899329829371336">"Ukjent app"</string>
+ <string name="media_output_dialog_button_stop_casting" msgid="6581379537930199189">"Stopp castingen"</string>
<string name="build_number_clip_data_label" msgid="3623176728412560914">"Delversjonsnummer"</string>
<string name="build_number_copy_toast" msgid="877720921605503046">"Delversjonsnummeret er kopiert til utklippstavlen."</string>
<string name="basic_status" msgid="2315371112182658176">"Åpen samtale"</string>
@@ -916,8 +914,6 @@
<string name="dream_overlay_status_bar_wifi_off" msgid="4497069245055003582">"Wi‑Fi er utilgjengelig"</string>
<string name="dream_overlay_status_bar_priority_mode" msgid="5428462123314728739">"Prioriteringsmodus"</string>
<string name="dream_overlay_status_bar_alarm_set" msgid="566707328356590886">"Alarmen er stilt inn"</string>
- <string name="dream_overlay_status_bar_assistant_guest_mode_enabled" msgid="3715897096012469615">"Gjestemodus for assistenten er slått på"</string>
<string name="dream_overlay_status_bar_camera_mic_off" msgid="3199425257833773569">"Kamera og mikrofon er av"</string>
- <!-- no translation found for dream_overlay_status_bar_notification_indicator (8091389255691081711) -->
- <skip />
+ <string name="dream_overlay_status_bar_notification_indicator" msgid="8091389255691081711">"{count,plural, =1{# varsel}other{# varsler}}"</string>
</resources>
diff --git a/packages/SystemUI/res/values-ne/strings.xml b/packages/SystemUI/res/values-ne/strings.xml
index 471bf14..bfe29aa 100644
--- a/packages/SystemUI/res/values-ne/strings.xml
+++ b/packages/SystemUI/res/values-ne/strings.xml
@@ -20,19 +20,17 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_label" msgid="4811759950673118541">"सिस्टम UI"</string>
- <!-- no translation found for battery_low_title (5319680173344341779) -->
- <skip />
- <!-- no translation found for battery_low_description (3282977755476423966) -->
- <skip />
- <!-- no translation found for battery_low_intro (5148725009653088790) -->
- <skip />
+ <string name="battery_low_title" msgid="5319680173344341779">"ब्याट्री सेभर अन गर्ने हो?"</string>
+ <string name="battery_low_description" msgid="3282977755476423966">"तपाईंको डिभाइसको ब्याट्रीको चार्ज <xliff:g id="PERCENTAGE">%s</xliff:g> बाँकी छ। ब्याट्री सेभरले अँध्यारो थिम अन गर्छ, ब्याकग्राउन्डमा हुने क्रियाकलाप सीमित पार्छ र सूचनाहरू ढिलो देखाउँछ।"</string>
+ <string name="battery_low_intro" msgid="5148725009653088790">"ब्याट्री सेभरले अँध्यारो थिम अन गर्छ, ब्याकग्राउन्डमा हुने क्रियाकलाप सीमित पार्छ र सूचनाहरू ढिलो देखाउँछ।"</string>
<string name="battery_low_percent_format" msgid="4276661262843170964">"<xliff:g id="PERCENTAGE">%s</xliff:g> बाँकी"</string>
<string name="invalid_charger_title" msgid="938685362320735167">"USB मार्फत चार्ज गर्न सकिँदैन"</string>
<string name="invalid_charger_text" msgid="2339310107232691577">"तपाईंको यन्त्रसँगै आएको चार्जर प्रयोग गर्नुहोस्"</string>
<string name="battery_saver_confirmation_title" msgid="1234998463717398453">"ब्याट्री सेभर सक्रिय गर्ने हो?"</string>
<string name="battery_saver_confirmation_title_generic" msgid="2299231884234959849">"ब्याट्री सेभरका बारेमा"</string>
<string name="battery_saver_confirmation_ok" msgid="5042136476802816494">"खोल्नुहोस्"</string>
- <string name="battery_saver_start_action" msgid="4553256017945469937">"ब्याट्री सेभर सक्रिय गर्नुहोस्"</string>
+ <string name="battery_saver_start_action" msgid="8353766979886287140">"अन गर्नुहोस्"</string>
+ <string name="battery_saver_dismiss_action" msgid="7199342621040014738">"पर्दैन"</string>
<string name="status_bar_settings_auto_rotation" msgid="8329080442278431708">"स्वत:घुम्ने स्क्रिन"</string>
<string name="usb_device_permission_prompt" msgid="4414719028369181772">"<xliff:g id="APPLICATION">%1$s</xliff:g> लाई <xliff:g id="USB_DEVICE">%2$s</xliff:g> माथि पहुँच राख्ने अनुमति दिने हो?"</string>
<string name="usb_device_permission_prompt_warn" msgid="2309129784984063656">"<xliff:g id="APPLICATION">%1$s</xliff:g> लाई <xliff:g id="USB_DEVICE">%2$s</xliff:g> माथि पहुँच राख्न अनुमति दिने हो?\nयो एपलाई रेकर्ड गर्ने अनुमति प्रदान गरिएको छैन तर यसले USB यन्त्रमार्फत अडियो क्याप्चर गर्न सक्छ।"</string>
@@ -133,8 +131,7 @@
<string name="biometric_dialog_face_icon_description_authenticated" msgid="2242167416140740920">"अनुहार प्रमाणीकरण गरियो"</string>
<string name="biometric_dialog_face_icon_description_confirmed" msgid="7918067993953940778">"पुष्टि भयो"</string>
<string name="biometric_dialog_tap_confirm" msgid="9166350738859143358">"पूरा गर्नका लागि पुष्टि गर्नुहोस् नामक विकल्पमा ट्याप गर्नुहोस्"</string>
- <!-- no translation found for biometric_dialog_tap_confirm_with_face (1597899891472340950) -->
- <skip />
+ <string name="biometric_dialog_tap_confirm_with_face" msgid="1597899891472340950">"तपाईंको अनुहार प्रयोग गरी अनलक गरियो। जारी राख्न थिच्नुहोस्।"</string>
<string name="biometric_dialog_authenticated" msgid="7337147327545272484">"प्रमाणीकरण गरियो"</string>
<string name="biometric_dialog_use_pin" msgid="8385294115283000709">"PIN प्रयोग गर्नुहोस्"</string>
<string name="biometric_dialog_use_pattern" msgid="2315593393167211194">"ढाँचा प्रयोग गर्नुहोस्"</string>
@@ -462,8 +459,7 @@
<string name="wallet_secondary_label_device_locked" msgid="5175862019125370506">"यो वालेट प्रयोग गर्न डिभाइस अनलक गर्नुहोस्"</string>
<string name="wallet_error_generic" msgid="257704570182963611">"तपाईंका कार्डहरू प्राप्त गर्ने क्रममा समस्या भयो, कृपया पछि फेरि प्रयास गर्नुहोस्"</string>
<string name="wallet_lockscreen_settings_label" msgid="3539105300870383570">"लक स्क्रिनसम्बन्धी सेटिङ"</string>
- <string name="qr_code_scanner_title" msgid="5660820608548306581">"QR कोड"</string>
- <string name="qr_code_scanner_description" msgid="7937603775306661863">"स्क्यान गर्न ट्याप गर्नुहोस्"</string>
+ <string name="qr_code_scanner_title" msgid="5290201053875420785">"QR कोड स्क्यान गर्नुहोस्"</string>
<string name="status_bar_work" msgid="5238641949837091056">"कार्य प्रोफाइल"</string>
<string name="status_bar_airplane" msgid="4848702508684541009">"हवाइजहाज मोड"</string>
<string name="zen_alarm_warning" msgid="7844303238486849503">"तपाईँले आफ्नो अर्को अलार्म <xliff:g id="WHEN">%1$s</xliff:g> सुन्नुहुने छैन"</string>
@@ -827,6 +823,7 @@
<string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"नयाँ डिभाइस कनेक्ट गर्नुहोस्"</string>
<string name="media_output_dialog_launch_app_text" msgid="1527413319632586259">"यो सत्र कास्ट गर्न चाहनुहुन्छ भने कृपया एप खोल्नुहोस्।"</string>
<string name="media_output_dialog_unknown_launch_app_name" msgid="1084899329829371336">"अज्ञात एप"</string>
+ <string name="media_output_dialog_button_stop_casting" msgid="6581379537930199189">"कास्ट गर्न छाड्नुहोस्"</string>
<string name="build_number_clip_data_label" msgid="3623176728412560914">"बिल्ड नम्बर"</string>
<string name="build_number_copy_toast" msgid="877720921605503046">"बिल्ड नम्बर कपी गरी क्लिपबोर्डमा सारियो।"</string>
<string name="basic_status" msgid="2315371112182658176">"वार्तालाप खोल्नुहोस्"</string>
@@ -916,7 +913,6 @@
<string name="dream_overlay_status_bar_wifi_off" msgid="4497069245055003582">"Wi‑Fi उपलब्ध छैन"</string>
<string name="dream_overlay_status_bar_priority_mode" msgid="5428462123314728739">"प्राथमिकता मोड"</string>
<string name="dream_overlay_status_bar_alarm_set" msgid="566707328356590886">"अलार्म सेट गरिएको छ"</string>
- <string name="dream_overlay_status_bar_assistant_guest_mode_enabled" msgid="3715897096012469615">"सहायकको अतिथि मोड अन गरिएको छ"</string>
<string name="dream_overlay_status_bar_camera_mic_off" msgid="3199425257833773569">"क्यामेरा र माइक अफ छन्"</string>
<string name="dream_overlay_status_bar_notification_indicator" msgid="8091389255691081711">"{count,plural, =1{# वटा सूचना}other{# वटा सूचनाहरू}}"</string>
</resources>
diff --git a/packages/SystemUI/res/values-night/colors.xml b/packages/SystemUI/res/values-night/colors.xml
index 4b96d5d..3a638b1 100644
--- a/packages/SystemUI/res/values-night/colors.xml
+++ b/packages/SystemUI/res/values-night/colors.xml
@@ -67,10 +67,12 @@
<!-- media output dialog-->
<color name="media_dialog_background">@color/material_dynamic_neutral10</color>
- <color name="media_dialog_active_item_main_content">@color/material_dynamic_neutral10</color>
- <color name="media_dialog_inactive_item_main_content">@color/material_dynamic_neutral10</color>
- <color name="media_dialog_item_status">@color/material_dynamic_neutral10</color>
- <color name="media_dialog_item_background">@color/material_dynamic_secondary95</color>
+ <color name="media_dialog_item_main_content">@color/material_dynamic_primary90</color>
+ <color name="media_dialog_item_background">@color/material_dynamic_neutral_variant20</color>
+ <color name="media_dialog_connected_item_background">@color/material_dynamic_secondary20</color>
+ <color name="media_dialog_seekbar_progress">@color/material_dynamic_secondary40</color>
+ <color name="media_dialog_button_background">@color/material_dynamic_primary70</color>
+ <color name="media_dialog_solid_button_text">@color/material_dynamic_secondary20</color>
<!-- Biometric dialog colors -->
<color name="biometric_dialog_gray">#ffcccccc</color>
diff --git a/packages/SystemUI/res/values-nl/strings.xml b/packages/SystemUI/res/values-nl/strings.xml
index 047f99f..0f49b75 100644
--- a/packages/SystemUI/res/values-nl/strings.xml
+++ b/packages/SystemUI/res/values-nl/strings.xml
@@ -20,19 +20,17 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_label" msgid="4811759950673118541">"Systeem-UI"</string>
- <!-- no translation found for battery_low_title (5319680173344341779) -->
- <skip />
- <!-- no translation found for battery_low_description (3282977755476423966) -->
- <skip />
- <!-- no translation found for battery_low_intro (5148725009653088790) -->
- <skip />
+ <string name="battery_low_title" msgid="5319680173344341779">"Batterijbesparing aanzetten?"</string>
+ <string name="battery_low_description" msgid="3282977755476423966">"Je hebt nog <xliff:g id="PERCENTAGE">%s</xliff:g> batterij. Batterijbesparing zet het donkere thema aan, beperkt activiteit op de achtergrond en vertraagt meldingen."</string>
+ <string name="battery_low_intro" msgid="5148725009653088790">"Batterijbesparing zet het donkere thema aan, beperkt activiteit op de achtergrond en vertraagt meldingen."</string>
<string name="battery_low_percent_format" msgid="4276661262843170964">"Nog <xliff:g id="PERCENTAGE">%s</xliff:g>"</string>
<string name="invalid_charger_title" msgid="938685362320735167">"Kan niet opladen via USB"</string>
<string name="invalid_charger_text" msgid="2339310107232691577">"Gebruik de oplader die bij je apparaat is geleverd"</string>
<string name="battery_saver_confirmation_title" msgid="1234998463717398453">"Batterijbesparing aanzetten?"</string>
<string name="battery_saver_confirmation_title_generic" msgid="2299231884234959849">"Over Batterijbesparing"</string>
<string name="battery_saver_confirmation_ok" msgid="5042136476802816494">"Aanzetten"</string>
- <string name="battery_saver_start_action" msgid="4553256017945469937">"Batterijbesparing aanzetten"</string>
+ <string name="battery_saver_start_action" msgid="8353766979886287140">"Aanzetten"</string>
+ <string name="battery_saver_dismiss_action" msgid="7199342621040014738">"Nee"</string>
<string name="status_bar_settings_auto_rotation" msgid="8329080442278431708">"Scherm automatisch draaien"</string>
<string name="usb_device_permission_prompt" msgid="4414719028369181772">"<xliff:g id="APPLICATION">%1$s</xliff:g> toegang geven tot <xliff:g id="USB_DEVICE">%2$s</xliff:g>?"</string>
<string name="usb_device_permission_prompt_warn" msgid="2309129784984063656">"<xliff:g id="APPLICATION">%1$s</xliff:g> toegang geven tot <xliff:g id="USB_DEVICE">%2$s</xliff:g>?\nDeze app heeft geen opnamerechten gekregen, maar zou audio kunnen vastleggen via dit USB-apparaat."</string>
@@ -133,8 +131,7 @@
<string name="biometric_dialog_face_icon_description_authenticated" msgid="2242167416140740920">"Gezicht geverifieerd"</string>
<string name="biometric_dialog_face_icon_description_confirmed" msgid="7918067993953940778">"Bevestigd"</string>
<string name="biometric_dialog_tap_confirm" msgid="9166350738859143358">"Tik op Bevestigen om te voltooien"</string>
- <!-- no translation found for biometric_dialog_tap_confirm_with_face (1597899891472340950) -->
- <skip />
+ <string name="biometric_dialog_tap_confirm_with_face" msgid="1597899891472340950">"Ontgrendeld met je gezicht. Druk om door te gaan."</string>
<string name="biometric_dialog_authenticated" msgid="7337147327545272484">"Geverifieerd"</string>
<string name="biometric_dialog_use_pin" msgid="8385294115283000709">"Pincode gebruiken"</string>
<string name="biometric_dialog_use_pattern" msgid="2315593393167211194">"Patroon gebruiken"</string>
@@ -270,13 +267,13 @@
<string name="quick_settings_work_mode_label" msgid="6440531507319809121">"Werk-apps"</string>
<string name="quick_settings_night_display_label" msgid="8180030659141778180">"Nachtverlichting"</string>
<string name="quick_settings_night_secondary_label_on_at_sunset" msgid="3358706312129866626">"Aan bij zonsondergang"</string>
- <string name="quick_settings_night_secondary_label_until_sunrise" msgid="4063448287758262485">"Tot zonsopgang"</string>
+ <string name="quick_settings_night_secondary_label_until_sunrise" msgid="4063448287758262485">"Tot zonsopkomst"</string>
<string name="quick_settings_night_secondary_label_on_at" msgid="3584738542293528235">"Aan om <xliff:g id="TIME">%s</xliff:g>"</string>
<string name="quick_settings_secondary_label_until" msgid="1883981263191927372">"Tot <xliff:g id="TIME">%s</xliff:g>"</string>
<string name="quick_settings_ui_mode_night_label" msgid="1398928270610780470">"Donker thema"</string>
<string name="quick_settings_dark_mode_secondary_label_battery_saver" msgid="4990712734503013251">"Batterijbesparing"</string>
<string name="quick_settings_dark_mode_secondary_label_on_at_sunset" msgid="6017379738102015710">"Aan bij zonsondergang"</string>
- <string name="quick_settings_dark_mode_secondary_label_until_sunrise" msgid="4404885070316716472">"Tot zonsopgang"</string>
+ <string name="quick_settings_dark_mode_secondary_label_until_sunrise" msgid="4404885070316716472">"Tot zonsopkomst"</string>
<string name="quick_settings_dark_mode_secondary_label_on_at" msgid="5128758823486361279">"Aan om <xliff:g id="TIME">%s</xliff:g>"</string>
<string name="quick_settings_dark_mode_secondary_label_until" msgid="2289774641256492437">"Tot <xliff:g id="TIME">%s</xliff:g>"</string>
<string name="quick_settings_dark_mode_secondary_label_on_at_bedtime" msgid="2274300599408864897">"Aan als het bedtijd is"</string>
@@ -462,8 +459,8 @@
<string name="wallet_secondary_label_device_locked" msgid="5175862019125370506">"Ontgrendelen om te gebruiken"</string>
<string name="wallet_error_generic" msgid="257704570182963611">"Er is een probleem opgetreden bij het ophalen van je kaarten. Probeer het later opnieuw."</string>
<string name="wallet_lockscreen_settings_label" msgid="3539105300870383570">"Instellingen voor vergrendelscherm"</string>
- <string name="qr_code_scanner_title" msgid="5660820608548306581">"QR-code"</string>
- <string name="qr_code_scanner_description" msgid="7937603775306661863">"Tik om te scannen"</string>
+ <!-- no translation found for qr_code_scanner_title (5290201053875420785) -->
+ <skip />
<string name="status_bar_work" msgid="5238641949837091056">"Werkprofiel"</string>
<string name="status_bar_airplane" msgid="4848702508684541009">"Vliegtuigmodus"</string>
<string name="zen_alarm_warning" msgid="7844303238486849503">"Je hoort je volgende wekker niet <xliff:g id="WHEN">%1$s</xliff:g>"</string>
@@ -590,7 +587,7 @@
<string name="switch_bar_on" msgid="1770868129120096114">"Aan"</string>
<string name="switch_bar_off" msgid="5669805115416379556">"Uit"</string>
<string name="tile_unavailable" msgid="3095879009136616920">"Niet beschikbaar"</string>
- <string name="tile_disabled" msgid="373212051546573069">"Uit"</string>
+ <string name="tile_disabled" msgid="373212051546573069">"Uitgezet"</string>
<string name="nav_bar" msgid="4642708685386136807">"Navigatiebalk"</string>
<string name="nav_bar_layout" msgid="4716392484772899544">"Lay-out"</string>
<string name="left_nav_bar_button_type" msgid="2634852842345192790">"Extra knoptype links"</string>
@@ -827,8 +824,9 @@
<string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"Nieuw apparaat koppelen"</string>
<string name="media_output_dialog_launch_app_text" msgid="1527413319632586259">"Als je deze sessie wilt casten, open je de app."</string>
<string name="media_output_dialog_unknown_launch_app_name" msgid="1084899329829371336">"Onbekende app"</string>
- <string name="build_number_clip_data_label" msgid="3623176728412560914">"Build-nummer"</string>
- <string name="build_number_copy_toast" msgid="877720921605503046">"Build-nummer naar klembord gekopieerd."</string>
+ <string name="media_output_dialog_button_stop_casting" msgid="6581379537930199189">"Casten stoppen"</string>
+ <string name="build_number_clip_data_label" msgid="3623176728412560914">"Buildnummer"</string>
+ <string name="build_number_copy_toast" msgid="877720921605503046">"Buildnummer naar klembord gekopieerd."</string>
<string name="basic_status" msgid="2315371112182658176">"Gesprek openen"</string>
<string name="select_conversation_title" msgid="6716364118095089519">"Gesprekswidgets"</string>
<string name="select_conversation_text" msgid="3376048251434956013">"Tik op een gesprek om het toe te voegen aan je startscherm"</string>
@@ -916,7 +914,6 @@
<string name="dream_overlay_status_bar_wifi_off" msgid="4497069245055003582">"Wifi niet beschikbaar"</string>
<string name="dream_overlay_status_bar_priority_mode" msgid="5428462123314728739">"Prioriteitsmodus"</string>
<string name="dream_overlay_status_bar_alarm_set" msgid="566707328356590886">"Wekker gezet"</string>
- <string name="dream_overlay_status_bar_assistant_guest_mode_enabled" msgid="3715897096012469615">"Gastmodus voor de Assistent staat aan"</string>
<string name="dream_overlay_status_bar_camera_mic_off" msgid="3199425257833773569">"Camera en microfoon staan uit"</string>
<string name="dream_overlay_status_bar_notification_indicator" msgid="8091389255691081711">"{count,plural, =1{# melding}other{# meldingen}}"</string>
</resources>
diff --git a/packages/SystemUI/res/values-or/strings.xml b/packages/SystemUI/res/values-or/strings.xml
index 0dca918..ed1fbbc 100644
--- a/packages/SystemUI/res/values-or/strings.xml
+++ b/packages/SystemUI/res/values-or/strings.xml
@@ -20,19 +20,17 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_label" msgid="4811759950673118541">"ସିଷ୍ଟମ୍ UI"</string>
- <!-- no translation found for battery_low_title (5319680173344341779) -->
- <skip />
- <!-- no translation found for battery_low_description (3282977755476423966) -->
- <skip />
- <!-- no translation found for battery_low_intro (5148725009653088790) -->
- <skip />
+ <string name="battery_low_title" msgid="5319680173344341779">"ବ୍ୟାଟେରୀ ସେଭର ଚାଲୁ କରିବେ?"</string>
+ <string name="battery_low_description" msgid="3282977755476423966">"ଆପଣଙ୍କର <xliff:g id="PERCENTAGE">%s</xliff:g> ବ୍ୟାଟେରୀ ଚାର୍ଜ ବାକି ଅଛି। ବ୍ୟାଟେରୀ ସେଭର ଗାଢ଼ା ଥିମକୁ ଚାଲୁ କରେ, ପୃଷ୍ଠପଟ କାର୍ଯ୍ୟକଳାପକୁ ପ୍ରତିବନ୍ଧିତ କରେ ଏବଂ ବିଜ୍ଞପ୍ତିଗୁଡ଼ିକୁ ବିଳମ୍ବିତ କରେ।"</string>
+ <string name="battery_low_intro" msgid="5148725009653088790">"ବ୍ୟାଟେରୀ ସେଭର ଗାଢ଼ା ଥିମକୁ ଚାଲୁ କରେ, ପୃଷ୍ଠପଟ କାର୍ଯ୍ୟକଳାପକୁ ପ୍ରତିବନ୍ଧିତ କରେ ଏବଂ ବିଜ୍ଞପ୍ତିଗୁଡ଼ିକୁ ବିଳମ୍ବିତ କରେ।"</string>
<string name="battery_low_percent_format" msgid="4276661262843170964">"<xliff:g id="PERCENTAGE">%s</xliff:g> ବାକି ଅଛି"</string>
<string name="invalid_charger_title" msgid="938685362320735167">"USB ଦ୍ଵାରା ଚାର୍ଜ କରିହେବନାହିଁ"</string>
<string name="invalid_charger_text" msgid="2339310107232691577">"ଆପଣଙ୍କ ଡିଭାଇସ୍ ପାଇଁ ଥିବା ଚାର୍ଜର୍କୁ ବ୍ୟବହାର କରନ୍ତୁ"</string>
<string name="battery_saver_confirmation_title" msgid="1234998463717398453">"ବ୍ୟାଟେରୀ ସେଭର୍ ଚାଲୁ କରିବେ?"</string>
<string name="battery_saver_confirmation_title_generic" msgid="2299231884234959849">"ବ୍ୟାଟେରୀ ସେଭର୍ ବିଷୟରେ"</string>
<string name="battery_saver_confirmation_ok" msgid="5042136476802816494">"ଚାଲୁ କରନ୍ତୁ"</string>
- <string name="battery_saver_start_action" msgid="4553256017945469937">"ବ୍ୟାଟେରୀ ସେଭର୍ ଚାଲୁ କରନ୍ତୁ"</string>
+ <string name="battery_saver_start_action" msgid="8353766979886287140">"ଚାଲୁ କରନ୍ତୁ"</string>
+ <string name="battery_saver_dismiss_action" msgid="7199342621040014738">"ନା, ଧନ୍ୟବାଦ"</string>
<string name="status_bar_settings_auto_rotation" msgid="8329080442278431708">"ଅଟୋ-ରୋଟେଟ୍ ସ୍କ୍ରିନ୍"</string>
<string name="usb_device_permission_prompt" msgid="4414719028369181772">"<xliff:g id="USB_DEVICE">%2$s</xliff:g> ଆକ୍ସେସ୍ କରିବାକୁ <xliff:g id="APPLICATION">%1$s</xliff:g>କୁ ଅନୁମତି ଦେବେ?"</string>
<string name="usb_device_permission_prompt_warn" msgid="2309129784984063656">"<xliff:g id="USB_DEVICE">%2$s</xliff:g> ଆକ୍ସେସ୍ କରିବାକୁ <xliff:g id="APPLICATION">%1$s</xliff:g>କୁ ଅନୁମତି ଦେବେ କି?\nଏହି ଆପ୍କୁ ରେକର୍ଡ କରିବାକୁ ଅନୁମତି ଦିଆଯାଇ ନାହିଁ କିନ୍ତୁ ଏହି USB ଡିଭାଇସ୍ ଜରିଆରେ ଅଡିଓ କ୍ୟାପ୍ଟର୍ କରିପାରିବ।"</string>
@@ -133,8 +131,7 @@
<string name="biometric_dialog_face_icon_description_authenticated" msgid="2242167416140740920">"ମୁହଁ ପ୍ରାମାଣିକତା ହୋଇଛି"</string>
<string name="biometric_dialog_face_icon_description_confirmed" msgid="7918067993953940778">"ସୁନିଶ୍ଚିତ କରାଯାଇଛି"</string>
<string name="biometric_dialog_tap_confirm" msgid="9166350738859143358">"ସମ୍ପୂର୍ଣ୍ଣ କରିବାକୁ ସୁନିଶ୍ଚିତ କରନ୍ତୁରେ ଟାପ୍ କରନ୍ତୁ"</string>
- <!-- no translation found for biometric_dialog_tap_confirm_with_face (1597899891472340950) -->
- <skip />
+ <string name="biometric_dialog_tap_confirm_with_face" msgid="1597899891472340950">"ଆପଣଙ୍କ ଫେସ ମାଧ୍ୟମରେ ଅନଲକ କରାଯାଇଛି। ଜାରି ରଖିବାକୁ ଦବାନ୍ତୁ।"</string>
<string name="biometric_dialog_authenticated" msgid="7337147327545272484">"ପ୍ରାମାଣିକତା ହୋଇଛି"</string>
<string name="biometric_dialog_use_pin" msgid="8385294115283000709">"PIN ବ୍ୟବହାର କରନ୍ତୁ"</string>
<string name="biometric_dialog_use_pattern" msgid="2315593393167211194">"ପାଟର୍ନ ବ୍ୟବହାର କରନ୍ତୁ"</string>
@@ -462,8 +459,8 @@
<string name="wallet_secondary_label_device_locked" msgid="5175862019125370506">"ବ୍ୟବହାର କରିବାକୁ ଅନଲକ୍ କରନ୍ତୁ"</string>
<string name="wallet_error_generic" msgid="257704570182963611">"ଆପଣଙ୍କ କାର୍ଡଗୁଡ଼ିକ ପାଇବାରେ ଏକ ସମସ୍ୟା ହୋଇଥିଲା। ଦୟାକରି ପରେ ପୁଣି ଚେଷ୍ଟା କରନ୍ତୁ"</string>
<string name="wallet_lockscreen_settings_label" msgid="3539105300870383570">"ସ୍କ୍ରିନ୍ ଲକ୍ ସେଟିଂସ୍"</string>
- <string name="qr_code_scanner_title" msgid="5660820608548306581">"QR କୋଡ"</string>
- <string name="qr_code_scanner_description" msgid="7937603775306661863">"ସ୍କାନ କରିବାକୁ ଟାପ କରନ୍ତୁ"</string>
+ <!-- no translation found for qr_code_scanner_title (5290201053875420785) -->
+ <skip />
<string name="status_bar_work" msgid="5238641949837091056">"ୱର୍କ ପ୍ରୋଫାଇଲ୍"</string>
<string name="status_bar_airplane" msgid="4848702508684541009">"ଏରୋପ୍ଲେନ୍ ମୋଡ୍"</string>
<string name="zen_alarm_warning" msgid="7844303238486849503">"<xliff:g id="WHEN">%1$s</xliff:g>ବେଳେ ଆପଣ ନିଜର ପରବର୍ତ୍ତୀ ଆଲାର୍ମ ଶୁଣିପାରିବେ ନାହିଁ"</string>
@@ -645,7 +642,7 @@
<string name="accessibility_desc_quick_settings_edit" msgid="741658939453595297">"ଦ୍ରୁତ ସେଟିଙ୍ଗ ଏଡିଟର୍।"</string>
<string name="accessibility_desc_notification_icon" msgid="7331265967584178674">"<xliff:g id="ID_1">%1$s</xliff:g> ବିଜ୍ଞପ୍ତି: <xliff:g id="ID_2">%2$s</xliff:g>"</string>
<string name="accessibility_quick_settings_settings" msgid="7098489591715844713">"ସେଟିଂସ୍ ଖୋଲନ୍ତୁ।"</string>
- <string name="accessibility_quick_settings_expand" msgid="2609275052412521467">"ଦ୍ରୁତ ସେଟିଙ୍ଗ ଖୋଲନ୍ତୁ।"</string>
+ <string name="accessibility_quick_settings_expand" msgid="2609275052412521467">"କ୍ଵିକ ସେଟିଂସ ଖୋଲନ୍ତୁ।"</string>
<string name="accessibility_quick_settings_collapse" msgid="4674876336725041982">"ଦ୍ରୁତ ସେଟିଂସ୍ ବନ୍ଦ କରନ୍ତୁ।"</string>
<string name="accessibility_quick_settings_user" msgid="505821942882668619">"<xliff:g id="ID_1">%s</xliff:g> ଭାବରେ ସାଇନ୍ ଇନ୍ କରିଛନ୍ତି"</string>
<string name="accessibility_quick_settings_choose_user_action" msgid="4554388498186576087">"ଉପଯୋଗକର୍ତ୍ତା ବାଛନ୍ତୁ"</string>
@@ -827,6 +824,7 @@
<string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"ନୂଆ ଡିଭାଇସକୁ ପେୟାର୍ କରନ୍ତୁ"</string>
<string name="media_output_dialog_launch_app_text" msgid="1527413319632586259">"ଏହି ସେସନକୁ କାଷ୍ଟ କରିବା ପାଇଁ, ଦୟାକରି ଆପ ଖୋଲନ୍ତୁ।"</string>
<string name="media_output_dialog_unknown_launch_app_name" msgid="1084899329829371336">"ଅଜଣା ଆପ"</string>
+ <string name="media_output_dialog_button_stop_casting" msgid="6581379537930199189">"କାଷ୍ଟ କରିବା ବନ୍ଦ କରନ୍ତୁ"</string>
<string name="build_number_clip_data_label" msgid="3623176728412560914">"ବିଲ୍ଡ ନମ୍ୱର"</string>
<string name="build_number_copy_toast" msgid="877720921605503046">"କ୍ଲିପବୋର୍ଡକୁ କପି କରାଯାଇଥିବା ବିଲ୍ଡ ନମ୍ୱର।"</string>
<string name="basic_status" msgid="2315371112182658176">"ବାର୍ତ୍ତାଳାପ ଖୋଲନ୍ତୁ"</string>
@@ -916,8 +914,6 @@
<string name="dream_overlay_status_bar_wifi_off" msgid="4497069245055003582">"ୱାଇ-ଫାଇ ଉପଲବ୍ଧ ନାହିଁ"</string>
<string name="dream_overlay_status_bar_priority_mode" msgid="5428462123314728739">"ପ୍ରାଥମିକତା ମୋଡ"</string>
<string name="dream_overlay_status_bar_alarm_set" msgid="566707328356590886">"ଆଲାରାମ ସେଟ"</string>
- <string name="dream_overlay_status_bar_assistant_guest_mode_enabled" msgid="3715897096012469615">"Assistantର ଅତିଥି ମୋଡ ସକ୍ଷମ କରାଯାଇଛି"</string>
<string name="dream_overlay_status_bar_camera_mic_off" msgid="3199425257833773569">"କ୍ୟାମେରା ଏବଂ ମାଇକ ବନ୍ଦ ଅଛି"</string>
- <!-- no translation found for dream_overlay_status_bar_notification_indicator (8091389255691081711) -->
- <skip />
+ <string name="dream_overlay_status_bar_notification_indicator" msgid="8091389255691081711">"{count,plural, =1{#ଟି ବିଜ୍ଞପ୍ତି}other{#ଟି ବିଜ୍ଞପ୍ତି}}"</string>
</resources>
diff --git a/packages/SystemUI/res/values-pa/strings.xml b/packages/SystemUI/res/values-pa/strings.xml
index faa2062..beda960 100644
--- a/packages/SystemUI/res/values-pa/strings.xml
+++ b/packages/SystemUI/res/values-pa/strings.xml
@@ -20,19 +20,17 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_label" msgid="4811759950673118541">"ਸਿਸਟਮ UI"</string>
- <!-- no translation found for battery_low_title (5319680173344341779) -->
- <skip />
- <!-- no translation found for battery_low_description (3282977755476423966) -->
- <skip />
- <!-- no translation found for battery_low_intro (5148725009653088790) -->
- <skip />
+ <string name="battery_low_title" msgid="5319680173344341779">"ਕੀ ਬੈਟਰੀ ਸੇਵਰ ਚਾਲੂ ਕਰਨਾ ਹੈ?"</string>
+ <string name="battery_low_description" msgid="3282977755476423966">"ਤੁਹਾਡੇ ਕੋਲ <xliff:g id="PERCENTAGE">%s</xliff:g> ਬੈਟਰੀ ਬਾਕੀ ਬਚੀ ਹੈ। ਬੈਟਰੀ ਸੇਵਰ ਗੂੜ੍ਹੇ ਥੀਮ ਨੂੰ ਚਾਲੂ ਕਰਦਾ ਹੈ, ਬੈਕਗ੍ਰਾਊਂਡ ਸਰਗਰਮੀ \'ਤੇ ਪਾਬੰਦੀ ਲਗਾਉਂਦਾ ਹੈ ਅਤੇ ਸੂਚਨਾਵਾਂ ਵਿੱਚ ਦੇਰੀ ਕਰਦਾ ਹੈ।"</string>
+ <string name="battery_low_intro" msgid="5148725009653088790">"ਬੈਟਰੀ ਸੇਵਰ ਗੂੜ੍ਹੇ ਥੀਮ ਨੂੰ ਚਾਲੂ ਕਰਦਾ ਹੈ, ਬੈਕਗ੍ਰਾਊਂਡ ਸਰਗਰਮੀ \'ਤੇ ਪਾਬੰਦੀ ਲਗਾਉਂਦਾ ਹੈ ਅਤੇ ਸੂਚਨਾਵਾਂ ਵਿੱਚ ਦੇਰੀ ਕਰਦਾ ਹੈ।"</string>
<string name="battery_low_percent_format" msgid="4276661262843170964">"<xliff:g id="PERCENTAGE">%s</xliff:g> ਬਾਕੀ"</string>
<string name="invalid_charger_title" msgid="938685362320735167">"USB ਰਾਹੀਂ ਚਾਰਜ ਨਹੀਂ ਕੀਤਾ ਜਾ ਸਕਦਾ"</string>
<string name="invalid_charger_text" msgid="2339310107232691577">"ਆਪਣੇ ਡੀਵਾਈਸ ਨਾਲ ਮਿਲੇ ਚਾਰਜਰ ਦੀ ਵਰਤੋਂ ਕਰੋ"</string>
<string name="battery_saver_confirmation_title" msgid="1234998463717398453">"ਕੀ ਬੈਟਰੀ ਸੇਵਰ ਚਾਲੂ ਕਰਨਾ ਹੈ?"</string>
<string name="battery_saver_confirmation_title_generic" msgid="2299231884234959849">"ਬੈਟਰੀ ਸੇਵਰ ਬਾਰੇ"</string>
<string name="battery_saver_confirmation_ok" msgid="5042136476802816494">"ਚਾਲੂ ਕਰੋ"</string>
- <string name="battery_saver_start_action" msgid="4553256017945469937">"ਬੈਟਰੀ ਸੇਵਰ ਚਾਲੂ ਕਰੋ"</string>
+ <string name="battery_saver_start_action" msgid="8353766979886287140">"ਚਾਲੂ ਕਰੋ"</string>
+ <string name="battery_saver_dismiss_action" msgid="7199342621040014738">"ਨਹੀਂ ਧੰਨਵਾਦ"</string>
<string name="status_bar_settings_auto_rotation" msgid="8329080442278431708">"ਸਕ੍ਰੀਨ ਸਵੈ-ਘੁਮਾਓ"</string>
<string name="usb_device_permission_prompt" msgid="4414719028369181772">"ਕੀ <xliff:g id="USB_DEVICE">%2$s</xliff:g> ਤੱਕ <xliff:g id="APPLICATION">%1$s</xliff:g> ਨੂੰ ਪਹੁੰਚ ਕਰਨ ਦੇਣੀ ਹੈ?"</string>
<string name="usb_device_permission_prompt_warn" msgid="2309129784984063656">"ਕੀ <xliff:g id="APPLICATION">%1$s</xliff:g> ਨੂੰ <xliff:g id="USB_DEVICE">%2$s</xliff:g> ਤੱਕ ਪਹੁੰਚ ਕਰਨ ਦੇਣੀ ਹੈ?\nਇਸ ਐਪ ਨੂੰ ਰਿਕਾਰਡ ਕਰਨ ਦੀ ਇਜਾਜ਼ਤ ਨਹੀਂ ਦਿੱਤੀ ਗਈ ਪਰ ਇਹ USB ਡੀਵਾਈਸ ਰਾਹੀਂ ਆਡੀਓ ਕੈਪਚਰ ਕਰ ਸਕਦੀ ਹੈ।"</string>
@@ -133,8 +131,7 @@
<string name="biometric_dialog_face_icon_description_authenticated" msgid="2242167416140740920">"ਚਿਹਰਾ ਪ੍ਰਮਾਣੀਕਿਰਤ ਹੋਇਆ"</string>
<string name="biometric_dialog_face_icon_description_confirmed" msgid="7918067993953940778">"ਪੁਸ਼ਟੀ ਕੀਤੀ ਗਈ"</string>
<string name="biometric_dialog_tap_confirm" msgid="9166350738859143358">"ਪੂਰਾ ਕਰਨ ਲਈ ਪੁਸ਼ਟੀ ਕਰੋ \'ਤੇ ਟੈਪ ਕਰੋ"</string>
- <!-- no translation found for biometric_dialog_tap_confirm_with_face (1597899891472340950) -->
- <skip />
+ <string name="biometric_dialog_tap_confirm_with_face" msgid="1597899891472340950">"ਤੁਹਾਡੇ ਚਿਹਰੇ ਵੱਲੋਂ ਅਣਲਾਕ ਕੀਤਾ ਗਿਆ। ਜਾਰੀ ਰੱਖਣ ਲਈ ਦਬਾਓ।"</string>
<string name="biometric_dialog_authenticated" msgid="7337147327545272484">"ਪ੍ਰਮਾਣਿਤ ਹੋਇਆ"</string>
<string name="biometric_dialog_use_pin" msgid="8385294115283000709">"ਪਿੰਨ ਵਰਤੋ"</string>
<string name="biometric_dialog_use_pattern" msgid="2315593393167211194">"ਪੈਟਰਨ ਵਰਤੋ"</string>
@@ -462,8 +459,8 @@
<string name="wallet_secondary_label_device_locked" msgid="5175862019125370506">"ਵਰਤਣ ਲਈ ਅਣਲਾਕ ਕਰੋ"</string>
<string name="wallet_error_generic" msgid="257704570182963611">"ਤੁਹਾਡੇ ਕਾਰਡ ਪ੍ਰਾਪਤ ਕਰਨ ਵਿੱਚ ਕੋਈ ਸਮੱਸਿਆ ਆਈ, ਕਿਰਪਾ ਕਰਕੇ ਬਾਅਦ ਵਿੱਚ ਦੁਬਾਰਾ ਕੋਸ਼ਿਸ਼ ਕਰੋ"</string>
<string name="wallet_lockscreen_settings_label" msgid="3539105300870383570">"ਲਾਕ ਸਕ੍ਰੀਨ ਸੈਟਿੰਗਾਂ"</string>
- <string name="qr_code_scanner_title" msgid="5660820608548306581">"QR ਕੋਡ"</string>
- <string name="qr_code_scanner_description" msgid="7937603775306661863">"ਸਕੈਨ ਕਰਨ ਲਈ ਟੈਪ ਕਰੋ"</string>
+ <!-- no translation found for qr_code_scanner_title (5290201053875420785) -->
+ <skip />
<string name="status_bar_work" msgid="5238641949837091056">"ਕਾਰਜ ਪ੍ਰੋਫਾਈਲ"</string>
<string name="status_bar_airplane" msgid="4848702508684541009">"ਹਵਾਈ-ਜਹਾਜ਼ ਮੋਡ"</string>
<string name="zen_alarm_warning" msgid="7844303238486849503">"ਤੁਸੀਂ <xliff:g id="WHEN">%1$s</xliff:g> ਵਜੇ ਆਪਣਾ ਅਗਲਾ ਅਲਾਰਮ ਨਹੀਂ ਸੁਣੋਗੇ"</string>
@@ -827,6 +824,7 @@
<string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"ਨਵਾਂ ਡੀਵਾਈਸ ਜੋੜਾਬੱਧ ਕਰੋ"</string>
<string name="media_output_dialog_launch_app_text" msgid="1527413319632586259">"ਇਸ ਸੈਸ਼ਨ ਨੂੰ ਕਾਸਟ ਕਰਨ ਲਈ, ਕਿਰਪਾ ਕਰਕੇ ਐਪ ਖੋਲ੍ਹੋ।"</string>
<string name="media_output_dialog_unknown_launch_app_name" msgid="1084899329829371336">"ਅਗਿਆਤ ਐਪ"</string>
+ <string name="media_output_dialog_button_stop_casting" msgid="6581379537930199189">"ਕਾਸਟ ਕਰਨਾ ਬੰਦ ਕਰੋ"</string>
<string name="build_number_clip_data_label" msgid="3623176728412560914">"ਬਿਲਡ ਨੰਬਰ"</string>
<string name="build_number_copy_toast" msgid="877720921605503046">"ਬਿਲਡ ਨੰਬਰ ਨੂੰ ਕਲਿੱਪਬੋਰਡ \'ਤੇ ਕਾਪੀ ਕੀਤਾ ਗਿਆ।"</string>
<string name="basic_status" msgid="2315371112182658176">"ਗੱਲਬਾਤ ਖੋਲ੍ਹੋ"</string>
@@ -916,8 +914,6 @@
<string name="dream_overlay_status_bar_wifi_off" msgid="4497069245055003582">"ਵਾਈ-ਫਾਈ ਉਪਲਬਧ ਨਹੀਂ ਹੈ"</string>
<string name="dream_overlay_status_bar_priority_mode" msgid="5428462123314728739">"ਤਰਜੀਹੀ ਮੋਡ"</string>
<string name="dream_overlay_status_bar_alarm_set" msgid="566707328356590886">"ਅਲਾਰਮ ਸੈੱਟ ਹੈ"</string>
- <string name="dream_overlay_status_bar_assistant_guest_mode_enabled" msgid="3715897096012469615">"Assistant ਮਹਿਮਾਨ ਮੋਡ ਚਾਲੂ ਹੈ"</string>
<string name="dream_overlay_status_bar_camera_mic_off" msgid="3199425257833773569">"ਕੈਮਰਾ ਅਤੇ ਮਾਈਕ ਬੰਦ ਹਨ"</string>
- <!-- no translation found for dream_overlay_status_bar_notification_indicator (8091389255691081711) -->
- <skip />
+ <string name="dream_overlay_status_bar_notification_indicator" msgid="8091389255691081711">"{count,plural, =1{# ਸੂਚਨਾ}one{# ਸੂਚਨਾ}other{# ਸੂਚਨਾਵਾਂ}}"</string>
</resources>
diff --git a/packages/SystemUI/res/values-pl/strings.xml b/packages/SystemUI/res/values-pl/strings.xml
index 5d61dfe..a2f94fc 100644
--- a/packages/SystemUI/res/values-pl/strings.xml
+++ b/packages/SystemUI/res/values-pl/strings.xml
@@ -20,19 +20,17 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_label" msgid="4811759950673118541">"UI systemu"</string>
- <!-- no translation found for battery_low_title (5319680173344341779) -->
- <skip />
- <!-- no translation found for battery_low_description (3282977755476423966) -->
- <skip />
- <!-- no translation found for battery_low_intro (5148725009653088790) -->
- <skip />
+ <string name="battery_low_title" msgid="5319680173344341779">"Włączyć Oszczędzanie baterii?"</string>
+ <string name="battery_low_description" msgid="3282977755476423966">"Masz już tylko <xliff:g id="PERCENTAGE">%s</xliff:g> baterii. Oszczędzanie baterii uruchamia ciemny motyw, ogranicza aktywność w tle i opóźnia powiadomienia."</string>
+ <string name="battery_low_intro" msgid="5148725009653088790">"Oszczędzanie baterii uruchamia ciemny motyw, ogranicza aktywność w tle i opóźnia powiadomienia."</string>
<string name="battery_low_percent_format" msgid="4276661262843170964">"Pozostało <xliff:g id="PERCENTAGE">%s</xliff:g>"</string>
<string name="invalid_charger_title" msgid="938685362320735167">"Nie można naładować przez USB"</string>
<string name="invalid_charger_text" msgid="2339310107232691577">"Użyj ładowarki dostarczonej z urządzeniem"</string>
<string name="battery_saver_confirmation_title" msgid="1234998463717398453">"Włączyć Oszczędzanie baterii?"</string>
<string name="battery_saver_confirmation_title_generic" msgid="2299231884234959849">"Informacje o Oszczędzaniu baterii"</string>
<string name="battery_saver_confirmation_ok" msgid="5042136476802816494">"Włącz"</string>
- <string name="battery_saver_start_action" msgid="4553256017945469937">"Włączyć Oszczędzanie baterii?"</string>
+ <string name="battery_saver_start_action" msgid="8353766979886287140">"Włącz"</string>
+ <string name="battery_saver_dismiss_action" msgid="7199342621040014738">"Nie, dziękuję"</string>
<string name="status_bar_settings_auto_rotation" msgid="8329080442278431708">"Autoobracanie ekranu"</string>
<string name="usb_device_permission_prompt" msgid="4414719028369181772">"Zezwolić aplikacji <xliff:g id="APPLICATION">%1$s</xliff:g> na dostęp do urządzenia <xliff:g id="USB_DEVICE">%2$s</xliff:g>?"</string>
<string name="usb_device_permission_prompt_warn" msgid="2309129784984063656">"Zezwolić aplikacji <xliff:g id="APPLICATION">%1$s</xliff:g> na dostęp do urządzenia <xliff:g id="USB_DEVICE">%2$s</xliff:g>?\nTa aplikacja nie ma uprawnień do nagrywania, ale może rejestrować dźwięk za pomocą tego urządzenia USB."</string>
@@ -133,8 +131,7 @@
<string name="biometric_dialog_face_icon_description_authenticated" msgid="2242167416140740920">"Twarz rozpoznana"</string>
<string name="biometric_dialog_face_icon_description_confirmed" msgid="7918067993953940778">"Potwierdzono"</string>
<string name="biometric_dialog_tap_confirm" msgid="9166350738859143358">"Aby zakończyć, kliknij Potwierdź"</string>
- <!-- no translation found for biometric_dialog_tap_confirm_with_face (1597899891472340950) -->
- <skip />
+ <string name="biometric_dialog_tap_confirm_with_face" msgid="1597899891472340950">"Odblokowano skanem twarzy. Kliknij, aby kontynuować."</string>
<string name="biometric_dialog_authenticated" msgid="7337147327545272484">"Uwierzytelniono"</string>
<string name="biometric_dialog_use_pin" msgid="8385294115283000709">"Użyj kodu PIN"</string>
<string name="biometric_dialog_use_pattern" msgid="2315593393167211194">"Użyj wzoru"</string>
@@ -468,8 +465,8 @@
<string name="wallet_secondary_label_device_locked" msgid="5175862019125370506">"Odblokuj, aby użyć"</string>
<string name="wallet_error_generic" msgid="257704570182963611">"Podczas pobierania kart wystąpił problem. Spróbuj ponownie później."</string>
<string name="wallet_lockscreen_settings_label" msgid="3539105300870383570">"Ustawienia ekranu blokady"</string>
- <string name="qr_code_scanner_title" msgid="5660820608548306581">"Kod QR"</string>
- <string name="qr_code_scanner_description" msgid="7937603775306661863">"Kliknij, aby zeskanować"</string>
+ <!-- no translation found for qr_code_scanner_title (5290201053875420785) -->
+ <skip />
<string name="status_bar_work" msgid="5238641949837091056">"Profil służbowy"</string>
<string name="status_bar_airplane" msgid="4848702508684541009">"Tryb samolotowy"</string>
<string name="zen_alarm_warning" msgid="7844303238486849503">"Nie usłyszysz swojego następnego alarmu <xliff:g id="WHEN">%1$s</xliff:g>"</string>
@@ -839,6 +836,7 @@
<string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"Sparuj nowe urządzenie"</string>
<string name="media_output_dialog_launch_app_text" msgid="1527413319632586259">"Aby przesłać tę sesję, otwórz aplikację."</string>
<string name="media_output_dialog_unknown_launch_app_name" msgid="1084899329829371336">"Nieznana aplikacja"</string>
+ <string name="media_output_dialog_button_stop_casting" msgid="6581379537930199189">"Zatrzymaj przesyłanie"</string>
<string name="build_number_clip_data_label" msgid="3623176728412560914">"Numer kompilacji"</string>
<string name="build_number_copy_toast" msgid="877720921605503046">"Numer kompilacji został skopiowany do schowka."</string>
<string name="basic_status" msgid="2315371112182658176">"Otwarta rozmowa"</string>
@@ -930,8 +928,6 @@
<string name="dream_overlay_status_bar_wifi_off" msgid="4497069245055003582">"Sieć Wi‑Fi niedostępna"</string>
<string name="dream_overlay_status_bar_priority_mode" msgid="5428462123314728739">"Tryb priorytetowy"</string>
<string name="dream_overlay_status_bar_alarm_set" msgid="566707328356590886">"Alarm ustawiony"</string>
- <string name="dream_overlay_status_bar_assistant_guest_mode_enabled" msgid="3715897096012469615">"Tryb gościa w Asystencie włączony"</string>
<string name="dream_overlay_status_bar_camera_mic_off" msgid="3199425257833773569">"Aparat i mikrofon są wyłączone"</string>
- <!-- no translation found for dream_overlay_status_bar_notification_indicator (8091389255691081711) -->
- <skip />
+ <string name="dream_overlay_status_bar_notification_indicator" msgid="8091389255691081711">"{count,plural, =1{# powiadomienie}few{# powiadomienia}many{# powiadomień}other{# powiadomienia}}"</string>
</resources>
diff --git a/packages/SystemUI/res/values-pt-rBR/strings.xml b/packages/SystemUI/res/values-pt-rBR/strings.xml
index d9bb15b..adc33a7 100644
--- a/packages/SystemUI/res/values-pt-rBR/strings.xml
+++ b/packages/SystemUI/res/values-pt-rBR/strings.xml
@@ -20,19 +20,17 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_label" msgid="4811759950673118541">"Interface do sistema"</string>
- <!-- no translation found for battery_low_title (5319680173344341779) -->
- <skip />
- <!-- no translation found for battery_low_description (3282977755476423966) -->
- <skip />
- <!-- no translation found for battery_low_intro (5148725009653088790) -->
- <skip />
+ <string name="battery_low_title" msgid="5319680173344341779">"Ativar Economia de bateria?"</string>
+ <string name="battery_low_description" msgid="3282977755476423966">"Você tem <xliff:g id="PERCENTAGE">%s</xliff:g> de bateria. A Economia de bateria ativa o tema escuro, restringe atividades em segundo plano e atrasa notificações."</string>
+ <string name="battery_low_intro" msgid="5148725009653088790">"A Economia de bateria ativa o tema escuro, restringe atividades em segundo plano e atrasa notificações."</string>
<string name="battery_low_percent_format" msgid="4276661262843170964">"<xliff:g id="PERCENTAGE">%s</xliff:g> restantes"</string>
<string name="invalid_charger_title" msgid="938685362320735167">"Não é possível carregar via USB"</string>
<string name="invalid_charger_text" msgid="2339310107232691577">"Usar o carregador que acompanha o dispositivo"</string>
<string name="battery_saver_confirmation_title" msgid="1234998463717398453">"Ativar \"Economia de bateria\"?"</string>
<string name="battery_saver_confirmation_title_generic" msgid="2299231884234959849">"Sobre a Economia de bateria"</string>
<string name="battery_saver_confirmation_ok" msgid="5042136476802816494">"Ativar"</string>
- <string name="battery_saver_start_action" msgid="4553256017945469937">"Ativar a Economia de bateria"</string>
+ <string name="battery_saver_start_action" msgid="8353766979886287140">"Ativar"</string>
+ <string name="battery_saver_dismiss_action" msgid="7199342621040014738">"Agora não"</string>
<string name="status_bar_settings_auto_rotation" msgid="8329080442278431708">"Giro automático da tela"</string>
<string name="usb_device_permission_prompt" msgid="4414719028369181772">"Permitir que o app <xliff:g id="APPLICATION">%1$s</xliff:g> acesse <xliff:g id="USB_DEVICE">%2$s</xliff:g>?"</string>
<string name="usb_device_permission_prompt_warn" msgid="2309129784984063656">"Permitir que <xliff:g id="APPLICATION">%1$s</xliff:g> acesse <xliff:g id="USB_DEVICE">%2$s</xliff:g>?\nEsse app não tem permissão de gravação, mas pode capturar áudio pelo dispositivo USB."</string>
@@ -133,8 +131,7 @@
<string name="biometric_dialog_face_icon_description_authenticated" msgid="2242167416140740920">"Rosto autenticado"</string>
<string name="biometric_dialog_face_icon_description_confirmed" msgid="7918067993953940778">"Confirmada"</string>
<string name="biometric_dialog_tap_confirm" msgid="9166350738859143358">"Toque em \"Confirmar\" para concluir"</string>
- <!-- no translation found for biometric_dialog_tap_confirm_with_face (1597899891472340950) -->
- <skip />
+ <string name="biometric_dialog_tap_confirm_with_face" msgid="1597899891472340950">"Desbloqueado pelo seu rosto. Pressione para continuar."</string>
<string name="biometric_dialog_authenticated" msgid="7337147327545272484">"Autenticado"</string>
<string name="biometric_dialog_use_pin" msgid="8385294115283000709">"Usar PIN"</string>
<string name="biometric_dialog_use_pattern" msgid="2315593393167211194">"Usar padrão"</string>
@@ -462,8 +459,7 @@
<string name="wallet_secondary_label_device_locked" msgid="5175862019125370506">"Desbloquear para usar"</string>
<string name="wallet_error_generic" msgid="257704570182963611">"Ocorreu um problema ao carregar os cards. Tente novamente mais tarde"</string>
<string name="wallet_lockscreen_settings_label" msgid="3539105300870383570">"Configurações de tela de bloqueio"</string>
- <string name="qr_code_scanner_title" msgid="5660820608548306581">"Código QR"</string>
- <string name="qr_code_scanner_description" msgid="7937603775306661863">"Toque para fazer a leitura"</string>
+ <string name="qr_code_scanner_title" msgid="5290201053875420785">"Ler código QR"</string>
<string name="status_bar_work" msgid="5238641949837091056">"Perfil de trabalho"</string>
<string name="status_bar_airplane" msgid="4848702508684541009">"Modo avião"</string>
<string name="zen_alarm_warning" msgid="7844303238486849503">"Você não ouvirá o próximo alarme às <xliff:g id="WHEN">%1$s</xliff:g>"</string>
@@ -827,6 +823,7 @@
<string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"Parear novo dispositivo"</string>
<string name="media_output_dialog_launch_app_text" msgid="1527413319632586259">"Abra o app para transmitir esta sessão."</string>
<string name="media_output_dialog_unknown_launch_app_name" msgid="1084899329829371336">"App desconhecido"</string>
+ <string name="media_output_dialog_button_stop_casting" msgid="6581379537930199189">"Parar transmissão"</string>
<string name="build_number_clip_data_label" msgid="3623176728412560914">"Número da versão"</string>
<string name="build_number_copy_toast" msgid="877720921605503046">"Número da versão copiado para a área de transferência."</string>
<string name="basic_status" msgid="2315371112182658176">"Conversa aberta"</string>
@@ -916,7 +913,6 @@
<string name="dream_overlay_status_bar_wifi_off" msgid="4497069245055003582">"Wi-Fi indisponível"</string>
<string name="dream_overlay_status_bar_priority_mode" msgid="5428462123314728739">"Modo de prioridade"</string>
<string name="dream_overlay_status_bar_alarm_set" msgid="566707328356590886">"Alarme definido"</string>
- <string name="dream_overlay_status_bar_assistant_guest_mode_enabled" msgid="3715897096012469615">"Modo visitante do Google Assistente ativado"</string>
<string name="dream_overlay_status_bar_camera_mic_off" msgid="3199425257833773569">"A câmera e o microfone estão desativados"</string>
<string name="dream_overlay_status_bar_notification_indicator" msgid="8091389255691081711">"{count,plural, =1{# notificação}one{# notificação}other{# notificações}}"</string>
</resources>
diff --git a/packages/SystemUI/res/values-pt-rPT/strings.xml b/packages/SystemUI/res/values-pt-rPT/strings.xml
index 73ef834..79f33fb 100644
--- a/packages/SystemUI/res/values-pt-rPT/strings.xml
+++ b/packages/SystemUI/res/values-pt-rPT/strings.xml
@@ -20,19 +20,17 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_label" msgid="4811759950673118541">"IU do sistema"</string>
- <!-- no translation found for battery_low_title (5319680173344341779) -->
- <skip />
- <!-- no translation found for battery_low_description (3282977755476423966) -->
- <skip />
- <!-- no translation found for battery_low_intro (5148725009653088790) -->
- <skip />
+ <string name="battery_low_title" msgid="5319680173344341779">"Ativar a Poupança de bateria?"</string>
+ <string name="battery_low_description" msgid="3282977755476423966">"Resta-lhe <xliff:g id="PERCENTAGE">%s</xliff:g> de bateria. A Poupança de bateria ativa o tema escuro, restringe a atividade em segundo plano e atrasa as notificações."</string>
+ <string name="battery_low_intro" msgid="5148725009653088790">"A Poupança de bateria ativa o tema escuro, restringe a atividade em segundo plano e atrasa as notificações."</string>
<string name="battery_low_percent_format" msgid="4276661262843170964">"<xliff:g id="PERCENTAGE">%s</xliff:g> restante"</string>
<string name="invalid_charger_title" msgid="938685362320735167">"Não é possível carregar através de USB."</string>
<string name="invalid_charger_text" msgid="2339310107232691577">"Utilize o carregador fornecido com o dispositivo."</string>
<string name="battery_saver_confirmation_title" msgid="1234998463717398453">"Pretende ativar a Poupança de bateria?"</string>
<string name="battery_saver_confirmation_title_generic" msgid="2299231884234959849">"Acerca da Poupança de bateria"</string>
<string name="battery_saver_confirmation_ok" msgid="5042136476802816494">"Ativar"</string>
- <string name="battery_saver_start_action" msgid="4553256017945469937">"Ativar a Poupança de bateria"</string>
+ <string name="battery_saver_start_action" msgid="8353766979886287140">"Ativar"</string>
+ <string name="battery_saver_dismiss_action" msgid="7199342621040014738">"Não"</string>
<string name="status_bar_settings_auto_rotation" msgid="8329080442278431708">"Rodar ecrã automaticamente"</string>
<string name="usb_device_permission_prompt" msgid="4414719028369181772">"Permitir que a app <xliff:g id="APPLICATION">%1$s</xliff:g> aceda ao dispositivo <xliff:g id="USB_DEVICE">%2$s</xliff:g>?"</string>
<string name="usb_device_permission_prompt_warn" msgid="2309129784984063656">"Permitir que <xliff:g id="APPLICATION">%1$s</xliff:g> aceda a <xliff:g id="USB_DEVICE">%2$s</xliff:g>?\nEsta app não recebeu autorização de gravação, mas pode capturar áudio através deste dispositivo USB."</string>
@@ -133,8 +131,7 @@
<string name="biometric_dialog_face_icon_description_authenticated" msgid="2242167416140740920">"Rosto autenticado"</string>
<string name="biometric_dialog_face_icon_description_confirmed" msgid="7918067993953940778">"Confirmado"</string>
<string name="biometric_dialog_tap_confirm" msgid="9166350738859143358">"Toque em Confirmar para concluir."</string>
- <!-- no translation found for biometric_dialog_tap_confirm_with_face (1597899891472340950) -->
- <skip />
+ <string name="biometric_dialog_tap_confirm_with_face" msgid="1597899891472340950">"Desbloqueado com o rosto. Prima para continuar."</string>
<string name="biometric_dialog_authenticated" msgid="7337147327545272484">"Autenticado"</string>
<string name="biometric_dialog_use_pin" msgid="8385294115283000709">"Utilizar PIN"</string>
<string name="biometric_dialog_use_pattern" msgid="2315593393167211194">"Utilizar padrão"</string>
@@ -205,8 +202,8 @@
<string name="accessibility_clear_all" msgid="970525598287244592">"Limpar todas as notificações."</string>
<string name="notification_group_overflow_indicator" msgid="7605120293801012648">"+ <xliff:g id="NUMBER">%s</xliff:g>"</string>
<plurals name="notification_group_overflow_description" formatted="false" msgid="91483442850649192">
- <item quantity="one">Mais <xliff:g id="NUMBER_0">%s</xliff:g> notificação no grupo.</item>
<item quantity="other">Mais <xliff:g id="NUMBER_1">%s</xliff:g> notificações no grupo.</item>
+ <item quantity="one">Mais <xliff:g id="NUMBER_0">%s</xliff:g> notificação no grupo.</item>
</plurals>
<string name="accessibility_rotation_lock_on_landscape" msgid="936972553861524360">"O ecrã está bloqueado na orientação horizontal."</string>
<string name="accessibility_rotation_lock_on_portrait" msgid="2356633398683813837">"O ecrã está bloqueado na orientação vertical."</string>
@@ -255,8 +252,8 @@
<string name="quick_settings_hotspot_secondary_label_transient" msgid="7585604088079160564">"A ativar..."</string>
<string name="quick_settings_hotspot_secondary_label_data_saver_enabled" msgid="1280433136266439372">"Poup. dados ativada"</string>
<plurals name="quick_settings_hotspot_secondary_label_num_devices" formatted="false" msgid="3142308865165871976">
- <item quantity="one">%d dispositivo</item>
<item quantity="other">%d dispositivos</item>
+ <item quantity="one">%d dispositivo</item>
</plurals>
<string name="quick_settings_flashlight_label" msgid="4904634272006284185">"Lanterna"</string>
<string name="quick_settings_flashlight_camera_in_use" msgid="4820591564526512571">"Câmara em utilização"</string>
@@ -339,8 +336,8 @@
<string name="user_add_user_message_short" msgid="2599370307878014791">"Ao adicionar um novo utilizador, essa pessoa tem de configurar o respetivo espaço.\n\nQualquer utilizador pode atualizar apps para todos os outros utilizadores."</string>
<string name="user_limit_reached_title" msgid="2429229448830346057">"Limite de utilizadores alcançado"</string>
<plurals name="user_limit_reached_message" formatted="false" msgid="2573535787802908398">
- <item quantity="one">Apenas é possível criar um utilizador.</item>
<item quantity="other">Pode adicionar até <xliff:g id="COUNT">%d</xliff:g> utilizadores.</item>
+ <item quantity="one">Apenas é possível criar um utilizador.</item>
</plurals>
<string name="user_remove_user_title" msgid="9124124694835811874">"Remover o utilizador?"</string>
<string name="user_remove_user_message" msgid="6702834122128031833">"Serão eliminados todos os dados e todas as aplicações deste utilizador."</string>
@@ -462,8 +459,8 @@
<string name="wallet_secondary_label_device_locked" msgid="5175862019125370506">"Desbloquear para utilizar"</string>
<string name="wallet_error_generic" msgid="257704570182963611">"Ocorreu um problema ao obter os seus cartões. Tente novamente mais tarde."</string>
<string name="wallet_lockscreen_settings_label" msgid="3539105300870383570">"Definições do ecrã de bloqueio"</string>
- <string name="qr_code_scanner_title" msgid="5660820608548306581">"Código QR"</string>
- <string name="qr_code_scanner_description" msgid="7937603775306661863">"Toque para ler"</string>
+ <!-- no translation found for qr_code_scanner_title (5290201053875420785) -->
+ <skip />
<string name="status_bar_work" msgid="5238641949837091056">"Perfil de trabalho"</string>
<string name="status_bar_airplane" msgid="4848702508684541009">"Modo de avião"</string>
<string name="zen_alarm_warning" msgid="7844303238486849503">"Não vai ouvir o próximo alarme às <xliff:g id="WHEN">%1$s</xliff:g>"</string>
@@ -528,12 +525,12 @@
<string name="snooze_undo" msgid="2738844148845992103">"Anular"</string>
<string name="snoozed_for_time" msgid="7586689374860469469">"Suspensa por <xliff:g id="TIME_AMOUNT">%1$s</xliff:g>"</string>
<plurals name="snoozeHourOptions" formatted="false" msgid="2066838694120718170">
- <item quantity="one">%d hora</item>
<item quantity="other">%d horas</item>
+ <item quantity="one">%d hora</item>
</plurals>
<plurals name="snoozeMinuteOptions" formatted="false" msgid="8998483159208055980">
- <item quantity="one">%d minuto</item>
<item quantity="other">%d minutos</item>
+ <item quantity="one">%d minuto</item>
</plurals>
<string name="battery_detail_switch_title" msgid="6940976502957380405">"Poupança de bateria"</string>
<string name="keyboard_key_button_template" msgid="8005673627272051429">"Botão <xliff:g id="NAME">%1$s</xliff:g>"</string>
@@ -756,8 +753,8 @@
<string name="quick_controls_title" msgid="6839108006171302273">"Controlos de dispositivos"</string>
<string name="controls_providers_title" msgid="6879775889857085056">"Escolha uma app para adicionar controlos"</string>
<plurals name="controls_number_of_favorites" formatted="false" msgid="1057347832073807380">
- <item quantity="one"><xliff:g id="NUMBER_0">%s</xliff:g> controlo adicionado.</item>
<item quantity="other"><xliff:g id="NUMBER_1">%s</xliff:g> controlos adicionados.</item>
+ <item quantity="one"><xliff:g id="NUMBER_0">%s</xliff:g> controlo adicionado.</item>
</plurals>
<string name="controls_removed" msgid="3731789252222856959">"Removido"</string>
<string name="accessibility_control_favorite" msgid="8694362691985545985">"Adicionado aos favoritos"</string>
@@ -827,6 +824,7 @@
<string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"Sincronize o novo dispositivo"</string>
<string name="media_output_dialog_launch_app_text" msgid="1527413319632586259">"Para transmitir esta sessão, abra a app."</string>
<string name="media_output_dialog_unknown_launch_app_name" msgid="1084899329829371336">"App desconhecida"</string>
+ <string name="media_output_dialog_button_stop_casting" msgid="6581379537930199189">"Parar transmissão"</string>
<string name="build_number_clip_data_label" msgid="3623176728412560914">"Número da compilação"</string>
<string name="build_number_copy_toast" msgid="877720921605503046">"Número da compilação copiado para a área de transferência."</string>
<string name="basic_status" msgid="2315371112182658176">"Abrir conversa"</string>
@@ -896,8 +894,8 @@
<string name="qs_tile_request_dialog_not_add" msgid="4168716573114067296">"Não adicion. mosaico"</string>
<string name="qs_user_switch_dialog_title" msgid="3045189293587781366">"Selecione utilizador"</string>
<plurals name="fgs_manager_footer_label" formatted="false" msgid="9091110396713032871">
- <item quantity="one"><xliff:g id="COUNT_0">%s</xliff:g> app ativa</item>
<item quantity="other"><xliff:g id="COUNT_1">%s</xliff:g> apps ativas</item>
+ <item quantity="one"><xliff:g id="COUNT_0">%s</xliff:g> app ativa</item>
</plurals>
<string name="fgs_dot_content_description" msgid="2865071539464777240">"Novas informações"</string>
<string name="fgs_manager_dialog_title" msgid="5879184257257718677">"Apps ativas"</string>
@@ -916,7 +914,6 @@
<string name="dream_overlay_status_bar_wifi_off" msgid="4497069245055003582">"Wi‑Fi indisponível"</string>
<string name="dream_overlay_status_bar_priority_mode" msgid="5428462123314728739">"Modo Prioridade"</string>
<string name="dream_overlay_status_bar_alarm_set" msgid="566707328356590886">"Alarme definido"</string>
- <string name="dream_overlay_status_bar_assistant_guest_mode_enabled" msgid="3715897096012469615">"Modo convidado do Assistente ativado"</string>
<string name="dream_overlay_status_bar_camera_mic_off" msgid="3199425257833773569">"A câmara e o microfone estão desativados"</string>
- <string name="dream_overlay_status_bar_notification_indicator" msgid="8091389255691081711">"{count,plural, =1{# notificação}one{# notificação(ões)}other{# notificações}}"</string>
+ <string name="dream_overlay_status_bar_notification_indicator" msgid="8091389255691081711">"{count,plural, =1{# notificação}other{# notificações}}"</string>
</resources>
diff --git a/packages/SystemUI/res/values-pt/strings.xml b/packages/SystemUI/res/values-pt/strings.xml
index d9bb15b..adc33a7 100644
--- a/packages/SystemUI/res/values-pt/strings.xml
+++ b/packages/SystemUI/res/values-pt/strings.xml
@@ -20,19 +20,17 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_label" msgid="4811759950673118541">"Interface do sistema"</string>
- <!-- no translation found for battery_low_title (5319680173344341779) -->
- <skip />
- <!-- no translation found for battery_low_description (3282977755476423966) -->
- <skip />
- <!-- no translation found for battery_low_intro (5148725009653088790) -->
- <skip />
+ <string name="battery_low_title" msgid="5319680173344341779">"Ativar Economia de bateria?"</string>
+ <string name="battery_low_description" msgid="3282977755476423966">"Você tem <xliff:g id="PERCENTAGE">%s</xliff:g> de bateria. A Economia de bateria ativa o tema escuro, restringe atividades em segundo plano e atrasa notificações."</string>
+ <string name="battery_low_intro" msgid="5148725009653088790">"A Economia de bateria ativa o tema escuro, restringe atividades em segundo plano e atrasa notificações."</string>
<string name="battery_low_percent_format" msgid="4276661262843170964">"<xliff:g id="PERCENTAGE">%s</xliff:g> restantes"</string>
<string name="invalid_charger_title" msgid="938685362320735167">"Não é possível carregar via USB"</string>
<string name="invalid_charger_text" msgid="2339310107232691577">"Usar o carregador que acompanha o dispositivo"</string>
<string name="battery_saver_confirmation_title" msgid="1234998463717398453">"Ativar \"Economia de bateria\"?"</string>
<string name="battery_saver_confirmation_title_generic" msgid="2299231884234959849">"Sobre a Economia de bateria"</string>
<string name="battery_saver_confirmation_ok" msgid="5042136476802816494">"Ativar"</string>
- <string name="battery_saver_start_action" msgid="4553256017945469937">"Ativar a Economia de bateria"</string>
+ <string name="battery_saver_start_action" msgid="8353766979886287140">"Ativar"</string>
+ <string name="battery_saver_dismiss_action" msgid="7199342621040014738">"Agora não"</string>
<string name="status_bar_settings_auto_rotation" msgid="8329080442278431708">"Giro automático da tela"</string>
<string name="usb_device_permission_prompt" msgid="4414719028369181772">"Permitir que o app <xliff:g id="APPLICATION">%1$s</xliff:g> acesse <xliff:g id="USB_DEVICE">%2$s</xliff:g>?"</string>
<string name="usb_device_permission_prompt_warn" msgid="2309129784984063656">"Permitir que <xliff:g id="APPLICATION">%1$s</xliff:g> acesse <xliff:g id="USB_DEVICE">%2$s</xliff:g>?\nEsse app não tem permissão de gravação, mas pode capturar áudio pelo dispositivo USB."</string>
@@ -133,8 +131,7 @@
<string name="biometric_dialog_face_icon_description_authenticated" msgid="2242167416140740920">"Rosto autenticado"</string>
<string name="biometric_dialog_face_icon_description_confirmed" msgid="7918067993953940778">"Confirmada"</string>
<string name="biometric_dialog_tap_confirm" msgid="9166350738859143358">"Toque em \"Confirmar\" para concluir"</string>
- <!-- no translation found for biometric_dialog_tap_confirm_with_face (1597899891472340950) -->
- <skip />
+ <string name="biometric_dialog_tap_confirm_with_face" msgid="1597899891472340950">"Desbloqueado pelo seu rosto. Pressione para continuar."</string>
<string name="biometric_dialog_authenticated" msgid="7337147327545272484">"Autenticado"</string>
<string name="biometric_dialog_use_pin" msgid="8385294115283000709">"Usar PIN"</string>
<string name="biometric_dialog_use_pattern" msgid="2315593393167211194">"Usar padrão"</string>
@@ -462,8 +459,7 @@
<string name="wallet_secondary_label_device_locked" msgid="5175862019125370506">"Desbloquear para usar"</string>
<string name="wallet_error_generic" msgid="257704570182963611">"Ocorreu um problema ao carregar os cards. Tente novamente mais tarde"</string>
<string name="wallet_lockscreen_settings_label" msgid="3539105300870383570">"Configurações de tela de bloqueio"</string>
- <string name="qr_code_scanner_title" msgid="5660820608548306581">"Código QR"</string>
- <string name="qr_code_scanner_description" msgid="7937603775306661863">"Toque para fazer a leitura"</string>
+ <string name="qr_code_scanner_title" msgid="5290201053875420785">"Ler código QR"</string>
<string name="status_bar_work" msgid="5238641949837091056">"Perfil de trabalho"</string>
<string name="status_bar_airplane" msgid="4848702508684541009">"Modo avião"</string>
<string name="zen_alarm_warning" msgid="7844303238486849503">"Você não ouvirá o próximo alarme às <xliff:g id="WHEN">%1$s</xliff:g>"</string>
@@ -827,6 +823,7 @@
<string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"Parear novo dispositivo"</string>
<string name="media_output_dialog_launch_app_text" msgid="1527413319632586259">"Abra o app para transmitir esta sessão."</string>
<string name="media_output_dialog_unknown_launch_app_name" msgid="1084899329829371336">"App desconhecido"</string>
+ <string name="media_output_dialog_button_stop_casting" msgid="6581379537930199189">"Parar transmissão"</string>
<string name="build_number_clip_data_label" msgid="3623176728412560914">"Número da versão"</string>
<string name="build_number_copy_toast" msgid="877720921605503046">"Número da versão copiado para a área de transferência."</string>
<string name="basic_status" msgid="2315371112182658176">"Conversa aberta"</string>
@@ -916,7 +913,6 @@
<string name="dream_overlay_status_bar_wifi_off" msgid="4497069245055003582">"Wi-Fi indisponível"</string>
<string name="dream_overlay_status_bar_priority_mode" msgid="5428462123314728739">"Modo de prioridade"</string>
<string name="dream_overlay_status_bar_alarm_set" msgid="566707328356590886">"Alarme definido"</string>
- <string name="dream_overlay_status_bar_assistant_guest_mode_enabled" msgid="3715897096012469615">"Modo visitante do Google Assistente ativado"</string>
<string name="dream_overlay_status_bar_camera_mic_off" msgid="3199425257833773569">"A câmera e o microfone estão desativados"</string>
<string name="dream_overlay_status_bar_notification_indicator" msgid="8091389255691081711">"{count,plural, =1{# notificação}one{# notificação}other{# notificações}}"</string>
</resources>
diff --git a/packages/SystemUI/res/values-ro/strings.xml b/packages/SystemUI/res/values-ro/strings.xml
index ff409d3..f57aa71 100644
--- a/packages/SystemUI/res/values-ro/strings.xml
+++ b/packages/SystemUI/res/values-ro/strings.xml
@@ -20,19 +20,17 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_label" msgid="4811759950673118541">"UI sistem"</string>
- <!-- no translation found for battery_low_title (5319680173344341779) -->
- <skip />
- <!-- no translation found for battery_low_description (3282977755476423966) -->
- <skip />
- <!-- no translation found for battery_low_intro (5148725009653088790) -->
- <skip />
+ <string name="battery_low_title" msgid="5319680173344341779">"Activați Economisirea bateriei?"</string>
+ <string name="battery_low_description" msgid="3282977755476423966">"Mai aveți <xliff:g id="PERCENTAGE">%s</xliff:g> din baterie. Economisirea bateriei activează Tema întunecată, restricționează activitatea în fundal și amână notificările."</string>
+ <string name="battery_low_intro" msgid="5148725009653088790">"Economisirea bateriei activează Tema întunecată, restricționează activitatea în fundal și amână notificările."</string>
<string name="battery_low_percent_format" msgid="4276661262843170964">"Procent rămas din baterie: <xliff:g id="PERCENTAGE">%s</xliff:g>"</string>
<string name="invalid_charger_title" msgid="938685362320735167">"Nu se poate realiza încărcarea prin USB"</string>
<string name="invalid_charger_text" msgid="2339310107232691577">"Folosiți încărcătorul livrat împreună cu dispozitivul"</string>
<string name="battery_saver_confirmation_title" msgid="1234998463717398453">"Activați economisirea bateriei?"</string>
<string name="battery_saver_confirmation_title_generic" msgid="2299231884234959849">"Despre Economisirea bateriei"</string>
<string name="battery_saver_confirmation_ok" msgid="5042136476802816494">"Activați"</string>
- <string name="battery_saver_start_action" msgid="4553256017945469937">"Activați economisirea bateriei"</string>
+ <string name="battery_saver_start_action" msgid="8353766979886287140">"Activați"</string>
+ <string name="battery_saver_dismiss_action" msgid="7199342621040014738">"Nu, mulțumesc"</string>
<string name="status_bar_settings_auto_rotation" msgid="8329080442278431708">"Rotire automată a ecranului"</string>
<string name="usb_device_permission_prompt" msgid="4414719028369181772">"Permiteți <xliff:g id="APPLICATION">%1$s</xliff:g> să acceseze <xliff:g id="USB_DEVICE">%2$s</xliff:g>?"</string>
<string name="usb_device_permission_prompt_warn" msgid="2309129784984063656">"Permiteți accesul aplicației <xliff:g id="APPLICATION">%1$s</xliff:g> la <xliff:g id="USB_DEVICE">%2$s</xliff:g>?\nPermisiunea de înregistrare nu a fost acordată aplicației, dar aceasta poate să înregistreze conținut audio prin intermediul acestui dispozitiv USB."</string>
@@ -133,8 +131,7 @@
<string name="biometric_dialog_face_icon_description_authenticated" msgid="2242167416140740920">"Chip autentificat"</string>
<string name="biometric_dialog_face_icon_description_confirmed" msgid="7918067993953940778">"Confirmat"</string>
<string name="biometric_dialog_tap_confirm" msgid="9166350738859143358">"Atingeți Confirmați pentru a finaliza"</string>
- <!-- no translation found for biometric_dialog_tap_confirm_with_face (1597899891472340950) -->
- <skip />
+ <string name="biometric_dialog_tap_confirm_with_face" msgid="1597899891472340950">"S-a deblocat cu ajutorul feței. Apăsați pentru a continua."</string>
<string name="biometric_dialog_authenticated" msgid="7337147327545272484">"Autentificat"</string>
<string name="biometric_dialog_use_pin" msgid="8385294115283000709">"Folosiți PIN-ul"</string>
<string name="biometric_dialog_use_pattern" msgid="2315593393167211194">"Folosiți modelul"</string>
@@ -465,8 +462,8 @@
<string name="wallet_secondary_label_device_locked" msgid="5175862019125370506">"Deblocați pentru a folosi"</string>
<string name="wallet_error_generic" msgid="257704570182963611">"A apărut o problemă la preluarea cardurilor. Încercați din nou mai târziu"</string>
<string name="wallet_lockscreen_settings_label" msgid="3539105300870383570">"Setările ecranului de blocare"</string>
- <string name="qr_code_scanner_title" msgid="5660820608548306581">"Cod QR"</string>
- <string name="qr_code_scanner_description" msgid="7937603775306661863">"Atingeți pentru a scana"</string>
+ <!-- no translation found for qr_code_scanner_title (5290201053875420785) -->
+ <skip />
<string name="status_bar_work" msgid="5238641949837091056">"Profil de serviciu"</string>
<string name="status_bar_airplane" msgid="4848702508684541009">"Mod Avion"</string>
<string name="zen_alarm_warning" msgid="7844303238486849503">"Nu veți auzi următoarea alarmă <xliff:g id="WHEN">%1$s</xliff:g>"</string>
@@ -833,6 +830,7 @@
<string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"Asociați un nou dispozitiv"</string>
<string name="media_output_dialog_launch_app_text" msgid="1527413319632586259">"Pentru a proiecta această sesiune, deschideți aplicația."</string>
<string name="media_output_dialog_unknown_launch_app_name" msgid="1084899329829371336">"Aplicație necunoscută"</string>
+ <string name="media_output_dialog_button_stop_casting" msgid="6581379537930199189">"Nu mai proiectați"</string>
<string name="build_number_clip_data_label" msgid="3623176728412560914">"Numărul versiunii"</string>
<string name="build_number_copy_toast" msgid="877720921605503046">"Numărul versiunii s-a copiat în clipboard."</string>
<string name="basic_status" msgid="2315371112182658176">"Deschideți conversația"</string>
@@ -923,8 +921,6 @@
<string name="dream_overlay_status_bar_wifi_off" msgid="4497069245055003582">"Wi‑Fi indisponibil"</string>
<string name="dream_overlay_status_bar_priority_mode" msgid="5428462123314728739">"Modul Prioritate"</string>
<string name="dream_overlay_status_bar_alarm_set" msgid="566707328356590886">"Alarmă setată"</string>
- <string name="dream_overlay_status_bar_assistant_guest_mode_enabled" msgid="3715897096012469615">"Modul pentru invitați al Asistentului este activat"</string>
<string name="dream_overlay_status_bar_camera_mic_off" msgid="3199425257833773569">"Camera și microfonul sunt dezactivate"</string>
- <!-- no translation found for dream_overlay_status_bar_notification_indicator (8091389255691081711) -->
- <skip />
+ <string name="dream_overlay_status_bar_notification_indicator" msgid="8091389255691081711">"{count,plural, =1{# notificare}few{# notificări}other{# de notificări}}"</string>
</resources>
diff --git a/packages/SystemUI/res/values-ru/strings.xml b/packages/SystemUI/res/values-ru/strings.xml
index a79c247..de09d76 100644
--- a/packages/SystemUI/res/values-ru/strings.xml
+++ b/packages/SystemUI/res/values-ru/strings.xml
@@ -20,19 +20,17 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_label" msgid="4811759950673118541">"Интерфейс системы"</string>
- <!-- no translation found for battery_low_title (5319680173344341779) -->
- <skip />
- <!-- no translation found for battery_low_description (3282977755476423966) -->
- <skip />
- <!-- no translation found for battery_low_intro (5148725009653088790) -->
- <skip />
+ <string name="battery_low_title" msgid="5319680173344341779">"Включить режим энергосбережения?"</string>
+ <string name="battery_low_description" msgid="3282977755476423966">"Уровень заряда батареи: <xliff:g id="PERCENTAGE">%s</xliff:g>. В режиме энергосбережения включается тёмная тема, ограничиваются фоновые процессы и приостанавливается показ уведомлений."</string>
+ <string name="battery_low_intro" msgid="5148725009653088790">"В режиме энергосбережения включается тёмная тема, ограничиваются фоновые процессы и приостанавливается показ уведомлений."</string>
<string name="battery_low_percent_format" msgid="4276661262843170964">"Осталось: <xliff:g id="PERCENTAGE">%s</xliff:g>"</string>
<string name="invalid_charger_title" msgid="938685362320735167">"Невозможно выполнить зарядку через USB"</string>
<string name="invalid_charger_text" msgid="2339310107232691577">"Используйте зарядное устройство из комплекта."</string>
<string name="battery_saver_confirmation_title" msgid="1234998463717398453">"Включить режим энергосбережения?"</string>
<string name="battery_saver_confirmation_title_generic" msgid="2299231884234959849">"О режиме энергосбережения"</string>
<string name="battery_saver_confirmation_ok" msgid="5042136476802816494">"Включить"</string>
- <string name="battery_saver_start_action" msgid="4553256017945469937">"Включить режим энергосбережения"</string>
+ <string name="battery_saver_start_action" msgid="8353766979886287140">"Включить"</string>
+ <string name="battery_saver_dismiss_action" msgid="7199342621040014738">"Нет"</string>
<string name="status_bar_settings_auto_rotation" msgid="8329080442278431708">"Автоповорот экрана"</string>
<string name="usb_device_permission_prompt" msgid="4414719028369181772">"Предоставить приложению \"<xliff:g id="APPLICATION">%1$s</xliff:g>\" доступ к устройству \"<xliff:g id="USB_DEVICE">%2$s</xliff:g>\"?"</string>
<string name="usb_device_permission_prompt_warn" msgid="2309129784984063656">"Предоставить приложению \"<xliff:g id="APPLICATION">%1$s</xliff:g>\" доступ к устройству \"<xliff:g id="USB_DEVICE">%2$s</xliff:g>\"?\nПриложению не разрешено вести запись, однако с помощью этого USB-устройства оно может записывать звук."</string>
@@ -133,8 +131,7 @@
<string name="biometric_dialog_face_icon_description_authenticated" msgid="2242167416140740920">"Лицо распознано"</string>
<string name="biometric_dialog_face_icon_description_confirmed" msgid="7918067993953940778">"Подтверждено"</string>
<string name="biometric_dialog_tap_confirm" msgid="9166350738859143358">"Нажмите \"Подтвердить\""</string>
- <!-- no translation found for biometric_dialog_tap_confirm_with_face (1597899891472340950) -->
- <skip />
+ <string name="biometric_dialog_tap_confirm_with_face" msgid="1597899891472340950">"Сработало распознавание лица. Нажмите, чтобы продолжить."</string>
<string name="biometric_dialog_authenticated" msgid="7337147327545272484">"Аутентификация выполнена"</string>
<string name="biometric_dialog_use_pin" msgid="8385294115283000709">"PIN-код"</string>
<string name="biometric_dialog_use_pattern" msgid="2315593393167211194">"Использовать графический ключ"</string>
@@ -468,8 +465,8 @@
<string name="wallet_secondary_label_device_locked" msgid="5175862019125370506">"Разблокировать для использования"</string>
<string name="wallet_error_generic" msgid="257704570182963611">"Не удалось получить информацию о картах. Повторите попытку позже."</string>
<string name="wallet_lockscreen_settings_label" msgid="3539105300870383570">"Настройки заблокированного экрана"</string>
- <string name="qr_code_scanner_title" msgid="5660820608548306581">"QR-код"</string>
- <string name="qr_code_scanner_description" msgid="7937603775306661863">"Нажмите, чтобы отсканировать код"</string>
+ <!-- no translation found for qr_code_scanner_title (5290201053875420785) -->
+ <skip />
<string name="status_bar_work" msgid="5238641949837091056">"Рабочий профиль"</string>
<string name="status_bar_airplane" msgid="4848702508684541009">"Режим полета"</string>
<string name="zen_alarm_warning" msgid="7844303238486849503">"Следующий будильник: <xliff:g id="WHEN">%1$s</xliff:g>. Звук отключен."</string>
@@ -839,6 +836,7 @@
<string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"Подключить новое устройство"</string>
<string name="media_output_dialog_launch_app_text" msgid="1527413319632586259">"Чтобы начать трансляцию сеанса, откройте приложение"</string>
<string name="media_output_dialog_unknown_launch_app_name" msgid="1084899329829371336">"Неизвестное приложение"</string>
+ <string name="media_output_dialog_button_stop_casting" msgid="6581379537930199189">"Остановить трансляцию"</string>
<string name="build_number_clip_data_label" msgid="3623176728412560914">"Номер сборки"</string>
<string name="build_number_copy_toast" msgid="877720921605503046">"Номер сборки скопирован в буфер обмена."</string>
<string name="basic_status" msgid="2315371112182658176">"Открытый чат"</string>
@@ -930,7 +928,6 @@
<string name="dream_overlay_status_bar_wifi_off" msgid="4497069245055003582">"Сеть Wi‑Fi недоступна"</string>
<string name="dream_overlay_status_bar_priority_mode" msgid="5428462123314728739">"Режим приоритета"</string>
<string name="dream_overlay_status_bar_alarm_set" msgid="566707328356590886">"Будильник установлен"</string>
- <string name="dream_overlay_status_bar_assistant_guest_mode_enabled" msgid="3715897096012469615">"Гостевой режим для Ассистента включен"</string>
<string name="dream_overlay_status_bar_camera_mic_off" msgid="3199425257833773569">"Камера и микрофон отключены"</string>
<string name="dream_overlay_status_bar_notification_indicator" msgid="8091389255691081711">"{count,plural, =1{# уведомление}one{# уведомление}few{# уведомления}many{# уведомлений}other{# уведомления}}"</string>
</resources>
diff --git a/packages/SystemUI/res/values-si/strings.xml b/packages/SystemUI/res/values-si/strings.xml
index ffaa4bf..cdb0896 100644
--- a/packages/SystemUI/res/values-si/strings.xml
+++ b/packages/SystemUI/res/values-si/strings.xml
@@ -20,19 +20,17 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_label" msgid="4811759950673118541">"පද්ධති UI"</string>
- <!-- no translation found for battery_low_title (5319680173344341779) -->
- <skip />
- <!-- no translation found for battery_low_description (3282977755476423966) -->
- <skip />
- <!-- no translation found for battery_low_intro (5148725009653088790) -->
- <skip />
+ <string name="battery_low_title" msgid="5319680173344341779">"බැටරි සුරැකුම ක්රියාත්මක කරන්නද?"</string>
+ <string name="battery_low_description" msgid="3282977755476423966">"ඔබට බැටරිය <xliff:g id="PERCENTAGE">%s</xliff:g> ඉතිරිව ඇත. බැටරි සුරැකුම අඳුරු තේමාව ක්රියාත්මක කරයි, පසුබිම් ක්රියාකාරකම සීමා කරයි, සහ දැනුම්දීම් ප්රමාද කරයි."</string>
+ <string name="battery_low_intro" msgid="5148725009653088790">"බැටරි සුරැකුම අඳුරු තේමාව ක්රියාත්මක කරයි, පසුබිම් ක්රියාකාරකම සීමා කරයි, සහ දැනුම්දීම් ප්රමාද කරයි."</string>
<string name="battery_low_percent_format" msgid="4276661262843170964">"<xliff:g id="PERCENTAGE">%s</xliff:g> ඉතිරිව තිබේ"</string>
<string name="invalid_charger_title" msgid="938685362320735167">"USB හරහා ආරෝපණය කළ නොහැකිය"</string>
<string name="invalid_charger_text" msgid="2339310107232691577">"ඔබේ උපාංගය සමඟ පැමිණි ආරෝපකය භාවිත කරන්න"</string>
<string name="battery_saver_confirmation_title" msgid="1234998463717398453">"බැටරි සුරැකුම ක්රියාත්මක කරන්නද?"</string>
<string name="battery_saver_confirmation_title_generic" msgid="2299231884234959849">"බැටරි සුරැකුම ගැන"</string>
<string name="battery_saver_confirmation_ok" msgid="5042136476802816494">"ක්රියාත්මක කරන්න"</string>
- <string name="battery_saver_start_action" msgid="4553256017945469937">"බැටරි සුරැකුම ක්රියාත්මක කරන්න"</string>
+ <string name="battery_saver_start_action" msgid="8353766979886287140">"ක්රියාත්මක කරන්න"</string>
+ <string name="battery_saver_dismiss_action" msgid="7199342621040014738">"එපා ස්තුතියි"</string>
<string name="status_bar_settings_auto_rotation" msgid="8329080442278431708">"ස්වයංක්රීයව-භ්රමණය වන තිරය"</string>
<string name="usb_device_permission_prompt" msgid="4414719028369181772">"<xliff:g id="APPLICATION">%1$s</xliff:g> හට <xliff:g id="USB_DEVICE">%2$s</xliff:g> වෙත පිවිසීමට ඉඩ දෙන්නද?"</string>
<string name="usb_device_permission_prompt_warn" msgid="2309129784984063656">"<xliff:g id="APPLICATION">%1$s</xliff:g> වෙත ප්රවේශ වීමට <xliff:g id="USB_DEVICE">%2$s</xliff:g> හට ඉඩ දෙන්නද?\n මෙම යෙදුමට පටිගත කිරීම් අවසරයක් ලබා දී නොමැති නමුත් මෙම USB උපාංගය හරහා ශ්රව්ය ග්රහණය කර ගත හැකිය."</string>
@@ -133,8 +131,7 @@
<string name="biometric_dialog_face_icon_description_authenticated" msgid="2242167416140740920">"මුහුණ සත්යාපන කළා"</string>
<string name="biometric_dialog_face_icon_description_confirmed" msgid="7918067993953940778">"තහවුරු කළා"</string>
<string name="biometric_dialog_tap_confirm" msgid="9166350738859143358">"සම්පූර්ණ කිරීමට තහවුරු කරන්න තට්ටු කර."</string>
- <!-- no translation found for biometric_dialog_tap_confirm_with_face (1597899891472340950) -->
- <skip />
+ <string name="biometric_dialog_tap_confirm_with_face" msgid="1597899891472340950">"ඔබගේ මුහුණෙන් අගුලු හරින ලදී. ඉදිරියට යාමට ඔබන්න."</string>
<string name="biometric_dialog_authenticated" msgid="7337147327545272484">"සත්යාපනය විය"</string>
<string name="biometric_dialog_use_pin" msgid="8385294115283000709">"PIN භාවිත කරන්න"</string>
<string name="biometric_dialog_use_pattern" msgid="2315593393167211194">"රටාව භාවිත කරන්න"</string>
@@ -462,8 +459,8 @@
<string name="wallet_secondary_label_device_locked" msgid="5175862019125370506">"භාවිත කිරීමට අගුලු හරින්න"</string>
<string name="wallet_error_generic" msgid="257704570182963611">"ඔබගේ කාඩ්පත ලබා ගැනීමේ ගැටලුවක් විය, කරුණාකර පසුව නැවත උත්සාහ කරන්න"</string>
<string name="wallet_lockscreen_settings_label" msgid="3539105300870383570">"අගුලු තිර සැකසීම්"</string>
- <string name="qr_code_scanner_title" msgid="5660820608548306581">"QR කේතය"</string>
- <string name="qr_code_scanner_description" msgid="7937603775306661863">"ස්කෑන් කිරීමට තට්ටු කරන්න"</string>
+ <!-- no translation found for qr_code_scanner_title (5290201053875420785) -->
+ <skip />
<string name="status_bar_work" msgid="5238641949837091056">"කාර්යාල පැතිකඩ"</string>
<string name="status_bar_airplane" msgid="4848702508684541009">"ගුවන්යානා ප්රකාරය"</string>
<string name="zen_alarm_warning" msgid="7844303238486849503">"ඔබට ඔබේ ඊළඟ එලාමය <xliff:g id="WHEN">%1$s</xliff:g> නොඇසෙනු ඇත"</string>
@@ -827,6 +824,7 @@
<string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"නව උපාංගය යුගල කරන්න"</string>
<string name="media_output_dialog_launch_app_text" msgid="1527413319632586259">"මෙම සැසිය විකාශය කිරීමට, කරුණාකර යෙදුම විවෘත කරන්න."</string>
<string name="media_output_dialog_unknown_launch_app_name" msgid="1084899329829371336">"නොදන්නා යෙදුම"</string>
+ <string name="media_output_dialog_button_stop_casting" msgid="6581379537930199189">"විකාශය නවතන්න"</string>
<string name="build_number_clip_data_label" msgid="3623176728412560914">"නිමැවුම් අංකය"</string>
<string name="build_number_copy_toast" msgid="877720921605503046">"නිමැවුම් අංකය පසුරු පුවරුවට පිටපත් කරන ලදි."</string>
<string name="basic_status" msgid="2315371112182658176">"සංවාදය විවෘත කරන්න"</string>
@@ -916,8 +914,6 @@
<string name="dream_overlay_status_bar_wifi_off" msgid="4497069245055003582">"Wi‑Fi ලබා ගත නොහැකිය"</string>
<string name="dream_overlay_status_bar_priority_mode" msgid="5428462123314728739">"ප්රමුඛතා ප්රකාරය"</string>
<string name="dream_overlay_status_bar_alarm_set" msgid="566707328356590886">"සීනුව සකසන ලදි"</string>
- <string name="dream_overlay_status_bar_assistant_guest_mode_enabled" msgid="3715897096012469615">"සහායක ආගන්තුක ප්රකාරය සබලයි"</string>
<string name="dream_overlay_status_bar_camera_mic_off" msgid="3199425257833773569">"කැමරාව සහ මයික් ක්රියාවිරහිතයි"</string>
- <!-- no translation found for dream_overlay_status_bar_notification_indicator (8091389255691081711) -->
- <skip />
+ <string name="dream_overlay_status_bar_notification_indicator" msgid="8091389255691081711">"{count,plural, =1{දැනුම්දීම් #ක්}one{දැනුම්දීම් #ක්}other{දැනුම්දීම් #ක්}}"</string>
</resources>
diff --git a/packages/SystemUI/res/values-sk/strings.xml b/packages/SystemUI/res/values-sk/strings.xml
index 2c2a7c8..5e29c93 100644
--- a/packages/SystemUI/res/values-sk/strings.xml
+++ b/packages/SystemUI/res/values-sk/strings.xml
@@ -20,19 +20,17 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_label" msgid="4811759950673118541">"UI systému"</string>
- <!-- no translation found for battery_low_title (5319680173344341779) -->
- <skip />
- <!-- no translation found for battery_low_description (3282977755476423966) -->
- <skip />
- <!-- no translation found for battery_low_intro (5148725009653088790) -->
- <skip />
+ <string name="battery_low_title" msgid="5319680173344341779">"Chcete zapnúť šetrič batérie?"</string>
+ <string name="battery_low_description" msgid="3282977755476423966">"Zostáva vám <xliff:g id="PERCENTAGE">%s</xliff:g> batérie. Šetrič batérie zapne tmavý motív, obmedzí aktivity na pozadí a odloží upozornenia."</string>
+ <string name="battery_low_intro" msgid="5148725009653088790">"Šetrič batérie zapne tmavý motív, obmedzí aktivity na pozadí a odloží upozornenia."</string>
<string name="battery_low_percent_format" msgid="4276661262843170964">"Zostáva <xliff:g id="PERCENTAGE">%s</xliff:g>"</string>
<string name="invalid_charger_title" msgid="938685362320735167">"Nedá sa nabíjať cez USB"</string>
<string name="invalid_charger_text" msgid="2339310107232691577">"Použite nabíjačku dodanú so zariadením"</string>
<string name="battery_saver_confirmation_title" msgid="1234998463717398453">"Zapnúť šetrič batérie?"</string>
<string name="battery_saver_confirmation_title_generic" msgid="2299231884234959849">"Šetrič batérie"</string>
<string name="battery_saver_confirmation_ok" msgid="5042136476802816494">"Zapnúť"</string>
- <string name="battery_saver_start_action" msgid="4553256017945469937">"Zapnúť šetrič batérie"</string>
+ <string name="battery_saver_start_action" msgid="8353766979886287140">"Zapnúť"</string>
+ <string name="battery_saver_dismiss_action" msgid="7199342621040014738">"Nie, vďaka"</string>
<string name="status_bar_settings_auto_rotation" msgid="8329080442278431708">"Automatické otočenie obrazovky"</string>
<string name="usb_device_permission_prompt" msgid="4414719028369181772">"Povoliť aplikácii <xliff:g id="APPLICATION">%1$s</xliff:g> prístup k zariadeniu <xliff:g id="USB_DEVICE">%2$s</xliff:g>?"</string>
<string name="usb_device_permission_prompt_warn" msgid="2309129784984063656">"Povoliť aplikácii <xliff:g id="APPLICATION">%1$s</xliff:g> pristupovať k zariadeniu <xliff:g id="USB_DEVICE">%2$s</xliff:g>?\nTejto aplikácii nebolo udelené povolenie na nahrávanie, môže však snímať zvuk cez toto zariadenie USB."</string>
@@ -133,8 +131,7 @@
<string name="biometric_dialog_face_icon_description_authenticated" msgid="2242167416140740920">"Tvár bola overená"</string>
<string name="biometric_dialog_face_icon_description_confirmed" msgid="7918067993953940778">"Potvrdené"</string>
<string name="biometric_dialog_tap_confirm" msgid="9166350738859143358">"Overenie dokončíte klepnutím na Potvrdiť"</string>
- <!-- no translation found for biometric_dialog_tap_confirm_with_face (1597899891472340950) -->
- <skip />
+ <string name="biometric_dialog_tap_confirm_with_face" msgid="1597899891472340950">"Odomkli ste svojou tvárou. Pokračujte stlačením."</string>
<string name="biometric_dialog_authenticated" msgid="7337147327545272484">"Overené"</string>
<string name="biometric_dialog_use_pin" msgid="8385294115283000709">"Použiť PIN"</string>
<string name="biometric_dialog_use_pattern" msgid="2315593393167211194">"Použiť vzor"</string>
@@ -468,8 +465,7 @@
<string name="wallet_secondary_label_device_locked" msgid="5175862019125370506">"Odomknúť a použiť"</string>
<string name="wallet_error_generic" msgid="257704570182963611">"Pri načítavaní kariet sa vyskytol problém. Skúste to neskôr."</string>
<string name="wallet_lockscreen_settings_label" msgid="3539105300870383570">"Nastavenia uzamknutej obrazovky"</string>
- <string name="qr_code_scanner_title" msgid="5660820608548306581">"QR kód"</string>
- <string name="qr_code_scanner_description" msgid="7937603775306661863">"Ak chcete skenovať, klepnite"</string>
+ <string name="qr_code_scanner_title" msgid="5290201053875420785">"Skenovanie QR kódu"</string>
<string name="status_bar_work" msgid="5238641949837091056">"Pracovný profil"</string>
<string name="status_bar_airplane" msgid="4848702508684541009">"Režim v lietadle"</string>
<string name="zen_alarm_warning" msgid="7844303238486849503">"Váš budík o <xliff:g id="WHEN">%1$s</xliff:g> sa nespustí"</string>
@@ -839,6 +835,7 @@
<string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"Spárovať nové zariadenie"</string>
<string name="media_output_dialog_launch_app_text" msgid="1527413319632586259">"Ak chcete túto reláciu prenášať, otvorte aplikáciu."</string>
<string name="media_output_dialog_unknown_launch_app_name" msgid="1084899329829371336">"Neznáma aplikácia"</string>
+ <string name="media_output_dialog_button_stop_casting" msgid="6581379537930199189">"Zastaviť prenos"</string>
<string name="build_number_clip_data_label" msgid="3623176728412560914">"Číslo zostavy"</string>
<string name="build_number_copy_toast" msgid="877720921605503046">"Číslo zostavy bolo skopírované do schránky."</string>
<string name="basic_status" msgid="2315371112182658176">"Otvorená konverzácia"</string>
@@ -930,7 +927,6 @@
<string name="dream_overlay_status_bar_wifi_off" msgid="4497069245055003582">"Wi‑Fi nie je k dispozícii"</string>
<string name="dream_overlay_status_bar_priority_mode" msgid="5428462123314728739">"Režim priority"</string>
<string name="dream_overlay_status_bar_alarm_set" msgid="566707328356590886">"Budík je nastavený"</string>
- <string name="dream_overlay_status_bar_assistant_guest_mode_enabled" msgid="3715897096012469615">"Režim Asistenta pre hostí je aktivovaný"</string>
<string name="dream_overlay_status_bar_camera_mic_off" msgid="3199425257833773569">"Kamera a mikrofón sú vypnuté"</string>
<string name="dream_overlay_status_bar_notification_indicator" msgid="8091389255691081711">"{count,plural, =1{# upozornenie}few{# upozornenia}many{# notifications}other{# upozornení}}"</string>
</resources>
diff --git a/packages/SystemUI/res/values-sl/strings.xml b/packages/SystemUI/res/values-sl/strings.xml
index 6996d56..cf9cb1c 100644
--- a/packages/SystemUI/res/values-sl/strings.xml
+++ b/packages/SystemUI/res/values-sl/strings.xml
@@ -20,19 +20,17 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_label" msgid="4811759950673118541">"Sistemski uporabniški vmesnik"</string>
- <!-- no translation found for battery_low_title (5319680173344341779) -->
- <skip />
- <!-- no translation found for battery_low_description (3282977755476423966) -->
- <skip />
- <!-- no translation found for battery_low_intro (5148725009653088790) -->
- <skip />
+ <string name="battery_low_title" msgid="5319680173344341779">"Želite vklopiti varčevanje z energijo baterije?"</string>
+ <string name="battery_low_description" msgid="3282977755476423966">"Preostala napolnjenost baterije: <xliff:g id="PERCENTAGE">%s</xliff:g>. Funkcija varčevanja z energijo baterije vklopi temno temo, omeji dejavnost v ozadju in prikazuje obvestila z zakasnitvijo."</string>
+ <string name="battery_low_intro" msgid="5148725009653088790">"Funkcija varčevanja z energijo baterije vklopi temno temo, omeji dejavnost v ozadju in prikazuje obvestila z zakasnitvijo."</string>
<string name="battery_low_percent_format" msgid="4276661262843170964">"Še <xliff:g id="PERCENTAGE">%s</xliff:g>"</string>
<string name="invalid_charger_title" msgid="938685362320735167">"Ni mogoče polniti prek USB-ja"</string>
<string name="invalid_charger_text" msgid="2339310107232691577">"Uporabite polnilnik, ki je bil priložen napravi"</string>
<string name="battery_saver_confirmation_title" msgid="1234998463717398453">"Želite vklopiti varčevanje z baterijo?"</string>
<string name="battery_saver_confirmation_title_generic" msgid="2299231884234959849">"O varčevanju z energijo baterije"</string>
<string name="battery_saver_confirmation_ok" msgid="5042136476802816494">"Vklopi"</string>
- <string name="battery_saver_start_action" msgid="4553256017945469937">"Vklop varčevanja z baterijo"</string>
+ <string name="battery_saver_start_action" msgid="8353766979886287140">"Vklopi"</string>
+ <string name="battery_saver_dismiss_action" msgid="7199342621040014738">"Ne, hvala"</string>
<string name="status_bar_settings_auto_rotation" msgid="8329080442278431708">"Samodejno zasukaj zaslon"</string>
<string name="usb_device_permission_prompt" msgid="4414719028369181772">"Ali aplikaciji <xliff:g id="APPLICATION">%1$s</xliff:g> dovolite dostop do dodatka USB <xliff:g id="USB_DEVICE">%2$s</xliff:g>?"</string>
<string name="usb_device_permission_prompt_warn" msgid="2309129784984063656">"Ali aplikaciji <xliff:g id="APPLICATION">%1$s</xliff:g> dovolite dostop do naprave <xliff:g id="USB_DEVICE">%2$s</xliff:g>?\nTa aplikacija sicer nima dovoljenja za snemanje, vendar bi lahko zajemala zvok prek te naprave USB."</string>
@@ -133,8 +131,7 @@
<string name="biometric_dialog_face_icon_description_authenticated" msgid="2242167416140740920">"Pristnost obraza je potrjena"</string>
<string name="biometric_dialog_face_icon_description_confirmed" msgid="7918067993953940778">"Potrjeno"</string>
<string name="biometric_dialog_tap_confirm" msgid="9166350738859143358">"Za dokončanje se dotaknite »Potrdite«"</string>
- <!-- no translation found for biometric_dialog_tap_confirm_with_face (1597899891472340950) -->
- <skip />
+ <string name="biometric_dialog_tap_confirm_with_face" msgid="1597899891472340950">"Odklenili ste z obrazom. Pritisnite za nadaljevanje."</string>
<string name="biometric_dialog_authenticated" msgid="7337147327545272484">"Preverjena pristnost"</string>
<string name="biometric_dialog_use_pin" msgid="8385294115283000709">"Uporabi kodo PIN"</string>
<string name="biometric_dialog_use_pattern" msgid="2315593393167211194">"Uporabi vzorec"</string>
@@ -468,8 +465,8 @@
<string name="wallet_secondary_label_device_locked" msgid="5175862019125370506">"Odklenite za uporabo"</string>
<string name="wallet_error_generic" msgid="257704570182963611">"Pri pridobivanju kartic je prišlo do težave. Poskusite znova pozneje."</string>
<string name="wallet_lockscreen_settings_label" msgid="3539105300870383570">"Nastavitve zaklepanja zaslona"</string>
- <string name="qr_code_scanner_title" msgid="5660820608548306581">"Koda QR"</string>
- <string name="qr_code_scanner_description" msgid="7937603775306661863">"Dotaknite se za optično branje"</string>
+ <!-- no translation found for qr_code_scanner_title (5290201053875420785) -->
+ <skip />
<string name="status_bar_work" msgid="5238641949837091056">"Profil za Android Work"</string>
<string name="status_bar_airplane" msgid="4848702508684541009">"Način za letalo"</string>
<string name="zen_alarm_warning" msgid="7844303238486849503">"Naslednjega alarma ob <xliff:g id="WHEN">%1$s</xliff:g> ne boste slišali"</string>
@@ -839,6 +836,7 @@
<string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"Seznanitev nove naprave"</string>
<string name="media_output_dialog_launch_app_text" msgid="1527413319632586259">"Če želite predvajati to sejo, odprite aplikacijo."</string>
<string name="media_output_dialog_unknown_launch_app_name" msgid="1084899329829371336">"Neznana aplikacija"</string>
+ <string name="media_output_dialog_button_stop_casting" msgid="6581379537930199189">"Ustavi predvajanje"</string>
<string name="build_number_clip_data_label" msgid="3623176728412560914">"Delovna različica"</string>
<string name="build_number_copy_toast" msgid="877720921605503046">"Delovna različica je bila kopirana v odložišče."</string>
<string name="basic_status" msgid="2315371112182658176">"Odprt pogovor"</string>
@@ -930,7 +928,6 @@
<string name="dream_overlay_status_bar_wifi_off" msgid="4497069245055003582">"Wi‑Fi ni na voljo."</string>
<string name="dream_overlay_status_bar_priority_mode" msgid="5428462123314728739">"Prednostni način"</string>
<string name="dream_overlay_status_bar_alarm_set" msgid="566707328356590886">"Alarm je nastavljen."</string>
- <string name="dream_overlay_status_bar_assistant_guest_mode_enabled" msgid="3715897096012469615">"Način za goste je omogočen za Pomočnika."</string>
<string name="dream_overlay_status_bar_camera_mic_off" msgid="3199425257833773569">"Fotoaparat in mikrofon sta izklopljena."</string>
<string name="dream_overlay_status_bar_notification_indicator" msgid="8091389255691081711">"{count,plural, =1{# obvestilo}one{# obvestilo}two{# obvestili}few{# obvestila}other{# obvestil}}"</string>
</resources>
diff --git a/packages/SystemUI/res/values-sq/strings.xml b/packages/SystemUI/res/values-sq/strings.xml
index bea8d83..fcf8868 100644
--- a/packages/SystemUI/res/values-sq/strings.xml
+++ b/packages/SystemUI/res/values-sq/strings.xml
@@ -20,19 +20,17 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_label" msgid="4811759950673118541">"Ndërfaqja e përdoruesit të sistemit"</string>
- <!-- no translation found for battery_low_title (5319680173344341779) -->
- <skip />
- <!-- no translation found for battery_low_description (3282977755476423966) -->
- <skip />
- <!-- no translation found for battery_low_intro (5148725009653088790) -->
- <skip />
+ <string name="battery_low_title" msgid="5319680173344341779">"Të aktivizohet \"Kursyesi i baterisë\"?"</string>
+ <string name="battery_low_description" msgid="3282977755476423966">"Ke <xliff:g id="PERCENTAGE">%s</xliff:g> bateri të mbetur. \"Kursyesi i baterisë\" aktivizon \"Temën e errët\", kufizon aktivitetet në sfond dhe vonon njoftimet."</string>
+ <string name="battery_low_intro" msgid="5148725009653088790">"\"Kursyesi i baterisë\" aktivizon \"Temën e errët\", kufizon aktivitetet në sfond dhe vonon njoftimet."</string>
<string name="battery_low_percent_format" msgid="4276661262843170964">"Ka mbetur edhe <xliff:g id="PERCENTAGE">%s</xliff:g>"</string>
<string name="invalid_charger_title" msgid="938685362320735167">"Nuk mund të ngarkohet përmes USB-së"</string>
<string name="invalid_charger_text" msgid="2339310107232691577">"Përdor karikuesin që ke marrë me pajisjen"</string>
<string name="battery_saver_confirmation_title" msgid="1234998463717398453">"Të aktivizohet \"Kursyesi i baterisë\"?"</string>
<string name="battery_saver_confirmation_title_generic" msgid="2299231884234959849">"Rreth \"Kursyesit të baterisë\""</string>
<string name="battery_saver_confirmation_ok" msgid="5042136476802816494">"Aktivizo"</string>
- <string name="battery_saver_start_action" msgid="4553256017945469937">"Aktivizo \"Kursyesin e baterisë\""</string>
+ <string name="battery_saver_start_action" msgid="8353766979886287140">"Aktivizo"</string>
+ <string name="battery_saver_dismiss_action" msgid="7199342621040014738">"Jo, faleminderit"</string>
<string name="status_bar_settings_auto_rotation" msgid="8329080442278431708">"Rrotullimi automatik i ekranit"</string>
<string name="usb_device_permission_prompt" msgid="4414719028369181772">"Të lejohet <xliff:g id="APPLICATION">%1$s</xliff:g> të ketë qasje te <xliff:g id="USB_DEVICE">%2$s</xliff:g>?"</string>
<string name="usb_device_permission_prompt_warn" msgid="2309129784984063656">"Dëshiron të lejosh që <xliff:g id="APPLICATION">%1$s</xliff:g> të ketë qasje te <xliff:g id="USB_DEVICE">%2$s</xliff:g>?\nKëtij aplikacioni nuk i është dhënë leje për regjistrim, por mund të regjistrojë audio përmes kësaj pajisjeje USB."</string>
@@ -133,8 +131,7 @@
<string name="biometric_dialog_face_icon_description_authenticated" msgid="2242167416140740920">"Fytyra u vërtetua"</string>
<string name="biometric_dialog_face_icon_description_confirmed" msgid="7918067993953940778">"Konfirmuar"</string>
<string name="biometric_dialog_tap_confirm" msgid="9166350738859143358">"Trokit \"Konfirmo\" për ta përfunduar"</string>
- <!-- no translation found for biometric_dialog_tap_confirm_with_face (1597899891472340950) -->
- <skip />
+ <string name="biometric_dialog_tap_confirm_with_face" msgid="1597899891472340950">"Shkyçur nga fytyra jote. Shtyp për të vazhduar."</string>
<string name="biometric_dialog_authenticated" msgid="7337147327545272484">"U vërtetua"</string>
<string name="biometric_dialog_use_pin" msgid="8385294115283000709">"Përdor kodin PIN"</string>
<string name="biometric_dialog_use_pattern" msgid="2315593393167211194">"Përdor motivin"</string>
@@ -462,8 +459,8 @@
<string name="wallet_secondary_label_device_locked" msgid="5175862019125370506">"Shkyçe për ta përdorur"</string>
<string name="wallet_error_generic" msgid="257704570182963611">"Pati një problem me marrjen e kartave të tua. Provo përsëri më vonë"</string>
<string name="wallet_lockscreen_settings_label" msgid="3539105300870383570">"Cilësimet e ekranit të kyçjes"</string>
- <string name="qr_code_scanner_title" msgid="5660820608548306581">"Kodi QR"</string>
- <string name="qr_code_scanner_description" msgid="7937603775306661863">"Trokit për të skanuar"</string>
+ <!-- no translation found for qr_code_scanner_title (5290201053875420785) -->
+ <skip />
<string name="status_bar_work" msgid="5238641949837091056">"Profili i punës"</string>
<string name="status_bar_airplane" msgid="4848702508684541009">"Modaliteti i aeroplanit"</string>
<string name="zen_alarm_warning" msgid="7844303238486849503">"Nuk do ta dëgjosh alarmin e radhës në <xliff:g id="WHEN">%1$s</xliff:g>"</string>
@@ -827,6 +824,7 @@
<string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"Çifto pajisjen e re"</string>
<string name="media_output_dialog_launch_app_text" msgid="1527413319632586259">"Hap aplikacionin për të transmetuar këtë seancë."</string>
<string name="media_output_dialog_unknown_launch_app_name" msgid="1084899329829371336">"Aplikacion i panjohur"</string>
+ <string name="media_output_dialog_button_stop_casting" msgid="6581379537930199189">"Ndalo transmetimin"</string>
<string name="build_number_clip_data_label" msgid="3623176728412560914">"Numri i ndërtimit"</string>
<string name="build_number_copy_toast" msgid="877720921605503046">"Numri i ndërtimit u kopjua te kujtesa e fragmenteve"</string>
<string name="basic_status" msgid="2315371112182658176">"Hap bisedën"</string>
@@ -916,8 +914,6 @@
<string name="dream_overlay_status_bar_wifi_off" msgid="4497069245055003582">"Wi‑Fi nuk ofrohet"</string>
<string name="dream_overlay_status_bar_priority_mode" msgid="5428462123314728739">"Modaliteti \"Me përparësi\""</string>
<string name="dream_overlay_status_bar_alarm_set" msgid="566707328356590886">"Alarmi është caktuar"</string>
- <string name="dream_overlay_status_bar_assistant_guest_mode_enabled" msgid="3715897096012469615">"Modaliteti \"vizitor\" i \"Asistentit\" është aktivizuar"</string>
<string name="dream_overlay_status_bar_camera_mic_off" msgid="3199425257833773569">"Kamera dhe mikrofoni janë joaktivë"</string>
- <!-- no translation found for dream_overlay_status_bar_notification_indicator (8091389255691081711) -->
- <skip />
+ <string name="dream_overlay_status_bar_notification_indicator" msgid="8091389255691081711">"{count,plural, =1{# njoftim}other{# njoftime}}"</string>
</resources>
diff --git a/packages/SystemUI/res/values-sr/strings.xml b/packages/SystemUI/res/values-sr/strings.xml
index f373eea..1025552 100644
--- a/packages/SystemUI/res/values-sr/strings.xml
+++ b/packages/SystemUI/res/values-sr/strings.xml
@@ -20,19 +20,17 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_label" msgid="4811759950673118541">"UI система"</string>
- <!-- no translation found for battery_low_title (5319680173344341779) -->
- <skip />
- <!-- no translation found for battery_low_description (3282977755476423966) -->
- <skip />
- <!-- no translation found for battery_low_intro (5148725009653088790) -->
- <skip />
+ <string name="battery_low_title" msgid="5319680173344341779">"Желите ли да укључите Уштеду батерије?"</string>
+ <string name="battery_low_description" msgid="3282977755476423966">"Преостали ниво напуњености батерије је <xliff:g id="PERCENTAGE">%s</xliff:g>. Уштеда батерије укључује Тамну тему, ограничава активности у позадини и одлаже обавештења."</string>
+ <string name="battery_low_intro" msgid="5148725009653088790">"Уштеда батерије укључује Тамну тему, ограничава активности у позадини и одлаже обавештења."</string>
<string name="battery_low_percent_format" msgid="4276661262843170964">"Још <xliff:g id="PERCENTAGE">%s</xliff:g>"</string>
<string name="invalid_charger_title" msgid="938685362320735167">"Пуњење преко USB-а није успело"</string>
<string name="invalid_charger_text" msgid="2339310107232691577">"Користите пуњач који сте добили уз уређај"</string>
<string name="battery_saver_confirmation_title" msgid="1234998463717398453">"Желите да укључите Уштеду батерије?"</string>
<string name="battery_saver_confirmation_title_generic" msgid="2299231884234959849">"О Уштеди батерије"</string>
<string name="battery_saver_confirmation_ok" msgid="5042136476802816494">"Укључи"</string>
- <string name="battery_saver_start_action" msgid="4553256017945469937">"Укључи Уштеду батерије"</string>
+ <string name="battery_saver_start_action" msgid="8353766979886287140">"Укључи"</string>
+ <string name="battery_saver_dismiss_action" msgid="7199342621040014738">"Не, хвала"</string>
<string name="status_bar_settings_auto_rotation" msgid="8329080442278431708">"Аутоматско ротирање екрана"</string>
<string name="usb_device_permission_prompt" msgid="4414719028369181772">"Желите ли да дозволите да <xliff:g id="APPLICATION">%1$s</xliff:g> приступа уређају <xliff:g id="USB_DEVICE">%2$s</xliff:g>?"</string>
<string name="usb_device_permission_prompt_warn" msgid="2309129784984063656">"Желите ли да дозволите да <xliff:g id="APPLICATION">%1$s</xliff:g> приступа уређају <xliff:g id="USB_DEVICE">%2$s</xliff:g>?\nОва апликација нема дозволу за снимање, али би могла да снима звук помоћу овог USB уређаја."</string>
@@ -133,8 +131,7 @@
<string name="biometric_dialog_face_icon_description_authenticated" msgid="2242167416140740920">"Лице је потврђено"</string>
<string name="biometric_dialog_face_icon_description_confirmed" msgid="7918067993953940778">"Потврђено"</string>
<string name="biometric_dialog_tap_confirm" msgid="9166350738859143358">"Додирните Потврди да бисте завршили"</string>
- <!-- no translation found for biometric_dialog_tap_confirm_with_face (1597899891472340950) -->
- <skip />
+ <string name="biometric_dialog_tap_confirm_with_face" msgid="1597899891472340950">"Откључали сте лицем. Притисните да бисте наставили."</string>
<string name="biometric_dialog_authenticated" msgid="7337147327545272484">"Идентитет је потврђен"</string>
<string name="biometric_dialog_use_pin" msgid="8385294115283000709">"Користите PIN"</string>
<string name="biometric_dialog_use_pattern" msgid="2315593393167211194">"Користите шаблон"</string>
@@ -465,8 +462,7 @@
<string name="wallet_secondary_label_device_locked" msgid="5175862019125370506">"Откључај ради коришћења"</string>
<string name="wallet_error_generic" msgid="257704570182963611">"Дошло је до проблема при преузимању картица. Пробајте поново касније"</string>
<string name="wallet_lockscreen_settings_label" msgid="3539105300870383570">"Подешавања закључаног екрана"</string>
- <string name="qr_code_scanner_title" msgid="5660820608548306581">"QR кôд"</string>
- <string name="qr_code_scanner_description" msgid="7937603775306661863">"Додирните да бисте скенирали"</string>
+ <string name="qr_code_scanner_title" msgid="5290201053875420785">"Скенирајте QR кôд"</string>
<string name="status_bar_work" msgid="5238641949837091056">"Пословни профил"</string>
<string name="status_bar_airplane" msgid="4848702508684541009">"Режим рада у авиону"</string>
<string name="zen_alarm_warning" msgid="7844303238486849503">"Нећете чути следећи аларм у <xliff:g id="WHEN">%1$s</xliff:g>"</string>
@@ -833,6 +829,7 @@
<string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"Упари нови уређај"</string>
<string name="media_output_dialog_launch_app_text" msgid="1527413319632586259">"Да бисте пребацивали ову сесију, отворите апликацију."</string>
<string name="media_output_dialog_unknown_launch_app_name" msgid="1084899329829371336">"Непозната апликација"</string>
+ <string name="media_output_dialog_button_stop_casting" msgid="6581379537930199189">"Заустави пребацивање"</string>
<string name="build_number_clip_data_label" msgid="3623176728412560914">"Број верзије"</string>
<string name="build_number_copy_toast" msgid="877720921605503046">"Број верзије је копиран у привремену меморију."</string>
<string name="basic_status" msgid="2315371112182658176">"Отворите конверзацију"</string>
@@ -923,8 +920,6 @@
<string name="dream_overlay_status_bar_wifi_off" msgid="4497069245055003582">"WiFi није доступан"</string>
<string name="dream_overlay_status_bar_priority_mode" msgid="5428462123314728739">"Приоритетни режим"</string>
<string name="dream_overlay_status_bar_alarm_set" msgid="566707328356590886">"Аларм је подешен"</string>
- <string name="dream_overlay_status_bar_assistant_guest_mode_enabled" msgid="3715897096012469615">"Омогућен је режим госта у Помоћнику"</string>
<string name="dream_overlay_status_bar_camera_mic_off" msgid="3199425257833773569">"Камера и микрофон су искључени"</string>
- <!-- no translation found for dream_overlay_status_bar_notification_indicator (8091389255691081711) -->
- <skip />
+ <string name="dream_overlay_status_bar_notification_indicator" msgid="8091389255691081711">"{count,plural, =1{# обавештење}one{# обавештење}few{# обавештења}other{# обавештења}}"</string>
</resources>
diff --git a/packages/SystemUI/res/values-sv/strings.xml b/packages/SystemUI/res/values-sv/strings.xml
index 638ba9f..ed89872 100644
--- a/packages/SystemUI/res/values-sv/strings.xml
+++ b/packages/SystemUI/res/values-sv/strings.xml
@@ -20,19 +20,17 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_label" msgid="4811759950673118541">"Gränssnitt"</string>
- <!-- no translation found for battery_low_title (5319680173344341779) -->
- <skip />
- <!-- no translation found for battery_low_description (3282977755476423966) -->
- <skip />
- <!-- no translation found for battery_low_intro (5148725009653088790) -->
- <skip />
+ <string name="battery_low_title" msgid="5319680173344341779">"Vill du aktivera batterisparläget?"</string>
+ <string name="battery_low_description" msgid="3282977755476423966">"<xliff:g id="PERCENTAGE">%s</xliff:g> av batteriet återstår. I batterisparläget aktiveras Mörkt tema, bakgrundsaktivitet begränsas och aviseringar skjuts upp."</string>
+ <string name="battery_low_intro" msgid="5148725009653088790">"I batterisparläget aktiveras Mörkt tema, bakgrundsaktivitet begränsas och aviseringar skjuts upp."</string>
<string name="battery_low_percent_format" msgid="4276661262843170964">"<xliff:g id="PERCENTAGE">%s</xliff:g> kvar"</string>
<string name="invalid_charger_title" msgid="938685362320735167">"Det går inte att ladda via USB"</string>
<string name="invalid_charger_text" msgid="2339310107232691577">"Använd laddaren som följde med enheten."</string>
<string name="battery_saver_confirmation_title" msgid="1234998463717398453">"Vill du aktivera batterisparläget?"</string>
<string name="battery_saver_confirmation_title_generic" msgid="2299231884234959849">"Om batterisparläget"</string>
<string name="battery_saver_confirmation_ok" msgid="5042136476802816494">"Aktivera"</string>
- <string name="battery_saver_start_action" msgid="4553256017945469937">"Aktivera batterisparläget"</string>
+ <string name="battery_saver_start_action" msgid="8353766979886287140">"Aktivera"</string>
+ <string name="battery_saver_dismiss_action" msgid="7199342621040014738">"Nej tack"</string>
<string name="status_bar_settings_auto_rotation" msgid="8329080442278431708">"Rotera skärmen automatiskt"</string>
<string name="usb_device_permission_prompt" msgid="4414719028369181772">"Vill du ge <xliff:g id="APPLICATION">%1$s</xliff:g> åtkomst till <xliff:g id="USB_DEVICE">%2$s</xliff:g>?"</string>
<string name="usb_device_permission_prompt_warn" msgid="2309129784984063656">"Vill du ge <xliff:g id="APPLICATION">%1$s</xliff:g> åtkomst till <xliff:g id="USB_DEVICE">%2$s</xliff:g>?\nAppen har inte fått inspelningsbehörighet men kan spela in ljud via denna USB-enhet."</string>
@@ -133,8 +131,7 @@
<string name="biometric_dialog_face_icon_description_authenticated" msgid="2242167416140740920">"Ansiktet har autentiserats"</string>
<string name="biometric_dialog_face_icon_description_confirmed" msgid="7918067993953940778">"Bekräftat"</string>
<string name="biometric_dialog_tap_confirm" msgid="9166350738859143358">"Slutför genom att trycka på Bekräfta"</string>
- <!-- no translation found for biometric_dialog_tap_confirm_with_face (1597899891472340950) -->
- <skip />
+ <string name="biometric_dialog_tap_confirm_with_face" msgid="1597899891472340950">"Låstes upp med ansiktet. Tryck för att fortsätta."</string>
<string name="biometric_dialog_authenticated" msgid="7337147327545272484">"Autentiserad"</string>
<string name="biometric_dialog_use_pin" msgid="8385294115283000709">"Använd pinkod"</string>
<string name="biometric_dialog_use_pattern" msgid="2315593393167211194">"Använd mönster"</string>
@@ -462,8 +459,8 @@
<string name="wallet_secondary_label_device_locked" msgid="5175862019125370506">"Lås upp för att använda"</string>
<string name="wallet_error_generic" msgid="257704570182963611">"Det gick inte att hämta dina kort. Försök igen senare."</string>
<string name="wallet_lockscreen_settings_label" msgid="3539105300870383570">"Inställningar för låsskärm"</string>
- <string name="qr_code_scanner_title" msgid="5660820608548306581">"QR-kod"</string>
- <string name="qr_code_scanner_description" msgid="7937603775306661863">"Tryck för att skanna"</string>
+ <!-- no translation found for qr_code_scanner_title (5290201053875420785) -->
+ <skip />
<string name="status_bar_work" msgid="5238641949837091056">"Jobbprofil"</string>
<string name="status_bar_airplane" msgid="4848702508684541009">"Flygplansläge"</string>
<string name="zen_alarm_warning" msgid="7844303238486849503">"Nästa alarm, kl. <xliff:g id="WHEN">%1$s</xliff:g>, kommer inte att höras"</string>
@@ -827,6 +824,7 @@
<string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"Parkoppla en ny enhet"</string>
<string name="media_output_dialog_launch_app_text" msgid="1527413319632586259">"Öppna appen om du vill casta den här sessionen."</string>
<string name="media_output_dialog_unknown_launch_app_name" msgid="1084899329829371336">"Okänd app"</string>
+ <string name="media_output_dialog_button_stop_casting" msgid="6581379537930199189">"Sluta casta"</string>
<string name="build_number_clip_data_label" msgid="3623176728412560914">"Versionsnummer"</string>
<string name="build_number_copy_toast" msgid="877720921605503046">"Versionsnumret har kopierats till urklipp."</string>
<string name="basic_status" msgid="2315371112182658176">"Öppen konversation"</string>
@@ -916,8 +914,6 @@
<string name="dream_overlay_status_bar_wifi_off" msgid="4497069245055003582">"Wifi är inte tillgängligt"</string>
<string name="dream_overlay_status_bar_priority_mode" msgid="5428462123314728739">"Prioritetsläge"</string>
<string name="dream_overlay_status_bar_alarm_set" msgid="566707328356590886">"Alarmet är aktiverat"</string>
- <string name="dream_overlay_status_bar_assistant_guest_mode_enabled" msgid="3715897096012469615">"Gästläget för assistenten är aktiverat"</string>
<string name="dream_overlay_status_bar_camera_mic_off" msgid="3199425257833773569">"Kameran och mikrofonen är avstängda"</string>
- <!-- no translation found for dream_overlay_status_bar_notification_indicator (8091389255691081711) -->
- <skip />
+ <string name="dream_overlay_status_bar_notification_indicator" msgid="8091389255691081711">"{count,plural, =1{# avisering}other{# aviseringar}}"</string>
</resources>
diff --git a/packages/SystemUI/res/values-sw/strings.xml b/packages/SystemUI/res/values-sw/strings.xml
index 931f634..2f184a1 100644
--- a/packages/SystemUI/res/values-sw/strings.xml
+++ b/packages/SystemUI/res/values-sw/strings.xml
@@ -20,19 +20,17 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_label" msgid="4811759950673118541">"Kiolesura"</string>
- <!-- no translation found for battery_low_title (5319680173344341779) -->
- <skip />
- <!-- no translation found for battery_low_description (3282977755476423966) -->
- <skip />
- <!-- no translation found for battery_low_intro (5148725009653088790) -->
- <skip />
+ <string name="battery_low_title" msgid="5319680173344341779">"Ungependa Kuwasha Kiokoa Betri?"</string>
+ <string name="battery_low_description" msgid="3282977755476423966">"Umebakiza asilimia <xliff:g id="PERCENTAGE">%s</xliff:g> ya betri. Kiokoa Betri kinawasha Mandhari meusi, kinazuia shughuli za chinichini na kuchelewesha arifa."</string>
+ <string name="battery_low_intro" msgid="5148725009653088790">"Kiokoa Betri kinawasha Mandhari meusi, kinazuia shughuli za chinichini na kuchelewesha arifa."</string>
<string name="battery_low_percent_format" msgid="4276661262843170964">"Imebakisha <xliff:g id="PERCENTAGE">%s</xliff:g>"</string>
<string name="invalid_charger_title" msgid="938685362320735167">"Haiwezi kuchaji kupitia USB"</string>
<string name="invalid_charger_text" msgid="2339310107232691577">"Tumia chaja ambayo ilikuja na kifaa chako"</string>
<string name="battery_saver_confirmation_title" msgid="1234998463717398453">"Ungependa Kuwasha Kiokoa Betri?"</string>
<string name="battery_saver_confirmation_title_generic" msgid="2299231884234959849">"Kuhusu Kiokoa betri"</string>
<string name="battery_saver_confirmation_ok" msgid="5042136476802816494">"Washa"</string>
- <string name="battery_saver_start_action" msgid="4553256017945469937">"Washa Kiokoa Betri"</string>
+ <string name="battery_saver_start_action" msgid="8353766979886287140">"Washa"</string>
+ <string name="battery_saver_dismiss_action" msgid="7199342621040014738">"Hapana"</string>
<string name="status_bar_settings_auto_rotation" msgid="8329080442278431708">"Skrini ijizungushe kiotomatiki"</string>
<string name="usb_device_permission_prompt" msgid="4414719028369181772">"Ungependa kuruhusu <xliff:g id="APPLICATION">%1$s</xliff:g> ifikie <xliff:g id="USB_DEVICE">%2$s</xliff:g>?"</string>
<string name="usb_device_permission_prompt_warn" msgid="2309129784984063656">"Ungependa kuruhusu <xliff:g id="APPLICATION">%1$s</xliff:g> ifikie <xliff:g id="USB_DEVICE">%2$s</xliff:g>?\nProgramu hii haijapewa ruhusa ya kurekodi lakini inaweza kurekodi sauti kupitia kifaa hiki cha USB."</string>
@@ -133,8 +131,7 @@
<string name="biometric_dialog_face_icon_description_authenticated" msgid="2242167416140740920">"Uso umethibitishwa"</string>
<string name="biometric_dialog_face_icon_description_confirmed" msgid="7918067993953940778">"Imethibitishwa"</string>
<string name="biometric_dialog_tap_confirm" msgid="9166350738859143358">"Gusa Thibitisha ili ukamilishe"</string>
- <!-- no translation found for biometric_dialog_tap_confirm_with_face (1597899891472340950) -->
- <skip />
+ <string name="biometric_dialog_tap_confirm_with_face" msgid="1597899891472340950">"Imefunguliwa kwa kutumia uso wako. Bonyeza ili uendelee."</string>
<string name="biometric_dialog_authenticated" msgid="7337147327545272484">"Umethibitishwa"</string>
<string name="biometric_dialog_use_pin" msgid="8385294115283000709">"Tumia PIN"</string>
<string name="biometric_dialog_use_pattern" msgid="2315593393167211194">"Tumia mchoro"</string>
@@ -462,8 +459,8 @@
<string name="wallet_secondary_label_device_locked" msgid="5175862019125370506">"Fungua ili utumie"</string>
<string name="wallet_error_generic" msgid="257704570182963611">"Hitilafu imetokea wakati wa kuleta kadi zako, tafadhali jaribu tena baadaye"</string>
<string name="wallet_lockscreen_settings_label" msgid="3539105300870383570">"Mipangilio ya kufunga skrini"</string>
- <string name="qr_code_scanner_title" msgid="5660820608548306581">"Msimbo wa QR"</string>
- <string name="qr_code_scanner_description" msgid="7937603775306661863">"Gusa ili uchanganue"</string>
+ <!-- no translation found for qr_code_scanner_title (5290201053875420785) -->
+ <skip />
<string name="status_bar_work" msgid="5238641949837091056">"Wasifu wa kazini"</string>
<string name="status_bar_airplane" msgid="4848702508684541009">"Hali ya ndegeni"</string>
<string name="zen_alarm_warning" msgid="7844303238486849503">"Hutasikia kengele yako inayofuata ya saa <xliff:g id="WHEN">%1$s</xliff:g>"</string>
@@ -827,6 +824,7 @@
<string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"Oanisha kifaa kipya"</string>
<string name="media_output_dialog_launch_app_text" msgid="1527413319632586259">"Ili utume kipindi hiki, tafadhali fungua programu."</string>
<string name="media_output_dialog_unknown_launch_app_name" msgid="1084899329829371336">"Programu isiyojulikana"</string>
+ <string name="media_output_dialog_button_stop_casting" msgid="6581379537930199189">"Acha kutuma"</string>
<string name="build_number_clip_data_label" msgid="3623176728412560914">"Nambari ya muundo"</string>
<string name="build_number_copy_toast" msgid="877720921605503046">"Nambari ya muundo imewekwa kwenye ubao wa kunakili."</string>
<string name="basic_status" msgid="2315371112182658176">"Fungua mazungumzo"</string>
@@ -916,8 +914,6 @@
<string name="dream_overlay_status_bar_wifi_off" msgid="4497069245055003582">"Wi-Fi haipatikani"</string>
<string name="dream_overlay_status_bar_priority_mode" msgid="5428462123314728739">"Hali ya kipaumbele"</string>
<string name="dream_overlay_status_bar_alarm_set" msgid="566707328356590886">"Kengele imewekwa"</string>
- <string name="dream_overlay_status_bar_assistant_guest_mode_enabled" msgid="3715897096012469615">"Matumizi ya wageni ya Mratibu yamewashwa"</string>
<string name="dream_overlay_status_bar_camera_mic_off" msgid="3199425257833773569">"Kamera na maikrofoni zimezimwa"</string>
- <!-- no translation found for dream_overlay_status_bar_notification_indicator (8091389255691081711) -->
- <skip />
+ <string name="dream_overlay_status_bar_notification_indicator" msgid="8091389255691081711">"{count,plural, =1{Arifa #}other{Arifa #}}"</string>
</resources>
diff --git a/packages/SystemUI/res/values-sw600dp-land/dimens.xml b/packages/SystemUI/res/values-sw600dp-land/dimens.xml
index c56ba7b..740697b 100644
--- a/packages/SystemUI/res/values-sw600dp-land/dimens.xml
+++ b/packages/SystemUI/res/values-sw600dp-land/dimens.xml
@@ -37,6 +37,7 @@
<dimen name="controls_task_view_right_margin">8dp</dimen>
<dimen name="split_shade_header_height">42dp</dimen>
+ <dimen name="status_bar_header_height_keyguard">42dp</dimen>
<!-- Distance that the full shade transition takes in order to complete by tapping on a button
like "expand". -->
@@ -53,6 +54,14 @@
the shade (in alpha) -->
<dimen name="lockscreen_shade_scrim_transition_distance">80dp</dimen>
+ <!-- The notifications scrim transition should start when the other scrims' transition is at
+ 95%. -->
+ <dimen name="lockscreen_shade_notifications_scrim_transition_delay">76dp</dimen>
+
+ <!-- The notifications scrim transition duration is 66.6% of the duration of the other scrims'
+ transition. -->
+ <dimen name="lockscreen_shade_notifications_scrim_transition_distance">53.28dp</dimen>
+
<!-- Distance that the full shade transition takes in order for the keyguard content on
NotificationPanelViewController to fully fade (e.g. Clock & Smartspace) -->
<dimen name="lockscreen_shade_npvc_keyguard_content_alpha_transition_distance">80dp</dimen>
diff --git a/packages/SystemUI/res/values-sw720dp-land/dimens.xml b/packages/SystemUI/res/values-sw720dp-land/dimens.xml
index f267088..bdd7049 100644
--- a/packages/SystemUI/res/values-sw720dp-land/dimens.xml
+++ b/packages/SystemUI/res/values-sw720dp-land/dimens.xml
@@ -24,6 +24,7 @@
<dimen name="keyguard_split_shade_top_margin">72dp</dimen>
<dimen name="split_shade_header_height">56dp</dimen>
+ <dimen name="status_bar_header_height_keyguard">56dp</dimen>
<dimen name="qs_media_session_height_expanded">184dp</dimen>
</resources>
diff --git a/packages/SystemUI/res/values-ta/strings.xml b/packages/SystemUI/res/values-ta/strings.xml
index e856294f..cd40c79 100644
--- a/packages/SystemUI/res/values-ta/strings.xml
+++ b/packages/SystemUI/res/values-ta/strings.xml
@@ -20,19 +20,17 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_label" msgid="4811759950673118541">"சாதனத்தின் UI"</string>
- <!-- no translation found for battery_low_title (5319680173344341779) -->
- <skip />
- <!-- no translation found for battery_low_description (3282977755476423966) -->
- <skip />
- <!-- no translation found for battery_low_intro (5148725009653088790) -->
- <skip />
+ <string name="battery_low_title" msgid="5319680173344341779">"பேட்டரி சேமிப்பானை இயக்கவா?"</string>
+ <string name="battery_low_description" msgid="3282977755476423966">"<xliff:g id="PERCENTAGE">%s</xliff:g> பேட்டரி மீதமுள்ளது. பேட்டரி சேமிப்பான் அம்சம் டார்க் தீமை இயக்கும், அத்துடன் பின்னணிச் செயல்பாடுகளைக் கட்டுப்படுத்தி, அறிவிப்புகளைத் தாமதப்படுத்தும்."</string>
+ <string name="battery_low_intro" msgid="5148725009653088790">"பேட்டரி சேமிப்பான் அம்சம் டார்க் தீமை இயக்கும், அத்துடன் பின்னணிச் செயல்பாடுகளைக் கட்டுப்படுத்தி, அறிவிப்புகளைத் தாமதப்படுத்தும்."</string>
<string name="battery_low_percent_format" msgid="4276661262843170964">"<xliff:g id="PERCENTAGE">%s</xliff:g> உள்ளது"</string>
<string name="invalid_charger_title" msgid="938685362320735167">"USB மூலம், சார்ஜ் செய்ய முடியாது"</string>
<string name="invalid_charger_text" msgid="2339310107232691577">"உங்கள் சாதனத்துடன் வழங்கப்பட்ட சார்ஜரைப் பயன்படுத்தவும்"</string>
<string name="battery_saver_confirmation_title" msgid="1234998463717398453">"பேட்டரி சேமிப்பானை ஆன் செய்யவா?"</string>
<string name="battery_saver_confirmation_title_generic" msgid="2299231884234959849">"பேட்டரி சேமிப்பான்- ஓர் அறிமுகம்"</string>
<string name="battery_saver_confirmation_ok" msgid="5042136476802816494">"இயக்கு"</string>
- <string name="battery_saver_start_action" msgid="4553256017945469937">"பேட்டரி சேமிப்பானை ஆன் செய்"</string>
+ <string name="battery_saver_start_action" msgid="8353766979886287140">"இயக்கு"</string>
+ <string name="battery_saver_dismiss_action" msgid="7199342621040014738">"வேண்டாம்"</string>
<string name="status_bar_settings_auto_rotation" msgid="8329080442278431708">"திரையைத் தானாகச் சுழற்று"</string>
<string name="usb_device_permission_prompt" msgid="4414719028369181772">"<xliff:g id="USB_DEVICE">%2$s</xliff:g>ஐ அணுக, <xliff:g id="APPLICATION">%1$s</xliff:g> ஆப்ஸை அனுமதிக்கவா?"</string>
<string name="usb_device_permission_prompt_warn" msgid="2309129784984063656">"<xliff:g id="USB_DEVICE">%2$s</xliff:g>ஐப் பயன்படுத்த <xliff:g id="APPLICATION">%1$s</xliff:g>ஐ அனுமதிக்கவா?\nஇந்த ஆப்ஸிற்கு ரெக்கார்டு செய்வதற்கான அனுமதி வழங்கப்படவில்லை, எனினும் இந்த USB சாதனம் மூலம் ஆடியோவைப் பதிவுசெய்யும்."</string>
@@ -133,8 +131,7 @@
<string name="biometric_dialog_face_icon_description_authenticated" msgid="2242167416140740920">"முகம் அங்கீகரிக்கப்பட்டது"</string>
<string name="biometric_dialog_face_icon_description_confirmed" msgid="7918067993953940778">"உறுதிப்படுத்தப்பட்டது"</string>
<string name="biometric_dialog_tap_confirm" msgid="9166350738859143358">"முடிக்க \'உறுதிப்படுத்துக\' என்பதை தட்டவும்"</string>
- <!-- no translation found for biometric_dialog_tap_confirm_with_face (1597899891472340950) -->
- <skip />
+ <string name="biometric_dialog_tap_confirm_with_face" msgid="1597899891472340950">"முகத்தை வைத்து அன்லாக் செய்யப்பட்டது. திறக்க அழுத்தவும்."</string>
<string name="biometric_dialog_authenticated" msgid="7337147327545272484">"அங்கீகரிக்கப்பட்டது"</string>
<string name="biometric_dialog_use_pin" msgid="8385294115283000709">"பின்னைப் பயன்படுத்து"</string>
<string name="biometric_dialog_use_pattern" msgid="2315593393167211194">"பேட்டர்னைப் பயன்படுத்து"</string>
@@ -411,10 +408,10 @@
<string name="volume_odi_captions_hint_disable" msgid="2518846326748183407">"முடக்கும்"</string>
<string name="screen_pinning_title" msgid="9058007390337841305">"ஆப்ஸ் பின் செய்யப்பட்டது"</string>
<string name="screen_pinning_description" msgid="8699395373875667743">"பொருத்தியதை அகற்றும் வரை இதைக் காட்சியில் வைக்கும். அகற்ற, முந்தையது மற்றும் மேலோட்டப் பார்வையைத் தொட்டுப் பிடிக்கவும்."</string>
- <string name="screen_pinning_description_recents_invisible" msgid="4564466648700390037">"இதற்கான பின்னை அகற்றும் வரை, இந்தப் பயன்முறை செயல்பாட்டிலேயே இருக்கும். அகற்றுவதற்கு, முந்தையது மற்றும் முகப்புப் பொத்தான்களைத் தொட்டுப் பிடிக்கவும்."</string>
+ <string name="screen_pinning_description_recents_invisible" msgid="4564466648700390037">"இதற்கான பின்னை அகற்றும் வரை, இந்தப் பயன்முறை செயல்பாட்டிலேயே இருக்கும். அகற்றுவதற்கு, முந்தையது மற்றும் முகப்பு பட்டன்களைத் தொட்டுப் பிடிக்கவும்."</string>
<string name="screen_pinning_description_gestural" msgid="7246323931831232068">"பின் செய்திருப்பதை அகற்றும் வரை இதைச் செயல்பாட்டில் வைத்திருக்கும். அதை அகற்றுவதற்கு மேல்நோக்கி ஸ்வைப் செய்து பிடித்திருக்கவும்."</string>
<string name="screen_pinning_description_accessible" msgid="7386449191953535332">"பொருத்தியதை அகற்றும் வரை இதைக் காட்சியில் வைக்கும். அகற்ற, மேலோட்டப் பார்வையைத் தொட்டுப் பிடிக்கவும்."</string>
- <string name="screen_pinning_description_recents_invisible_accessible" msgid="2857071808674481986">"இதற்கான பின்னை அகற்றும் வரை, இந்தப் பயன்முறை செயல்பாட்டிலேயே இருக்கும். அகற்றுவதற்கு, முகப்புப் பொத்தானைத் தொட்டுப் பிடிக்கவும்."</string>
+ <string name="screen_pinning_description_recents_invisible_accessible" msgid="2857071808674481986">"இதற்கான பின்னை அகற்றும் வரை, இந்தப் பயன்முறை செயல்பாட்டிலேயே இருக்கும். அகற்றுவதற்கு, முகப்புப் பட்டனைத் தொட்டுப் பிடிக்கவும்."</string>
<string name="screen_pinning_exposes_personal_data" msgid="8189852022981524789">"தனிப்பட்ட தரவு அணுகப்படக்கூடும் (தொடர்புகள், மின்னஞ்சலின் உள்ளடக்கம் போன்றவை)."</string>
<string name="screen_pinning_can_open_other_apps" msgid="7529756813231421455">"பின் செய்யப்பட்டிருக்கும் ஆப்ஸ் பிற ஆப்ஸைத் திறக்கக்கூடும்."</string>
<string name="screen_pinning_toast" msgid="8177286912533744328">"இந்த ஆப்ஸைப் பின்னிலிருந்து அகற்ற, \'பின்செல்\' மற்றும் \'மேலோட்டப் பார்வை\' பட்டன்களைத் தொட்டுப் பிடித்திருக்கவும்"</string>
@@ -462,8 +459,7 @@
<string name="wallet_secondary_label_device_locked" msgid="5175862019125370506">"பயன்படுத்துவதற்கு அன்லாக் செய்க"</string>
<string name="wallet_error_generic" msgid="257704570182963611">"உங்கள் கார்டுகளின் விவரங்களைப் பெறுவதில் சிக்கல் ஏற்பட்டது, பிறகு முயலவும்"</string>
<string name="wallet_lockscreen_settings_label" msgid="3539105300870383570">"பூட்டுத் திரை அமைப்புகள்"</string>
- <string name="qr_code_scanner_title" msgid="5660820608548306581">"QR குறியீடு"</string>
- <string name="qr_code_scanner_description" msgid="7937603775306661863">"ஸ்கேன் செய்யத் தட்டவும்"</string>
+ <string name="qr_code_scanner_title" msgid="5290201053875420785">"QR குறியீட்டை ஸ்கேன் செய்தல்"</string>
<string name="status_bar_work" msgid="5238641949837091056">"பணிக் கணக்கு"</string>
<string name="status_bar_airplane" msgid="4848702508684541009">"விமானப் பயன்முறை"</string>
<string name="zen_alarm_warning" msgid="7844303238486849503">"அடுத்த அலாரத்தை <xliff:g id="WHEN">%1$s</xliff:g> மணிக்கு கேட்க மாட்டீர்கள்"</string>
@@ -827,6 +823,7 @@
<string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"புதிய சாதனத்தை இணைத்தல்"</string>
<string name="media_output_dialog_launch_app_text" msgid="1527413319632586259">"இந்த அமர்வை அலைபரப்ப ஆப்ஸைத் திறங்கள்."</string>
<string name="media_output_dialog_unknown_launch_app_name" msgid="1084899329829371336">"அறியப்படாத ஆப்ஸ்"</string>
+ <string name="media_output_dialog_button_stop_casting" msgid="6581379537930199189">"அலைபரப்புவதை நிறுத்து"</string>
<string name="build_number_clip_data_label" msgid="3623176728412560914">"பதிப்பு எண்"</string>
<string name="build_number_copy_toast" msgid="877720921605503046">"பதிப்பு எண் கிளிப்போர்டுக்கு நகலெடுக்கப்பட்டது."</string>
<string name="basic_status" msgid="2315371112182658176">"திறந்தநிலை உரையாடல்"</string>
@@ -916,8 +913,6 @@
<string name="dream_overlay_status_bar_wifi_off" msgid="4497069245055003582">"வைஃபை கிடைக்கவில்லை"</string>
<string name="dream_overlay_status_bar_priority_mode" msgid="5428462123314728739">"முன்னுரிமைப் பயன்முறை"</string>
<string name="dream_overlay_status_bar_alarm_set" msgid="566707328356590886">"அலாரம் அமைக்கப்பட்டுள்ளது"</string>
- <string name="dream_overlay_status_bar_assistant_guest_mode_enabled" msgid="3715897096012469615">"Assistant கெஸ்ட் பயன்முறை இயக்கப்பட்டுள்ளது"</string>
<string name="dream_overlay_status_bar_camera_mic_off" msgid="3199425257833773569">"கேமராவும் மைக்கும் ஆஃப் செய்யப்பட்டுள்ளன"</string>
- <!-- no translation found for dream_overlay_status_bar_notification_indicator (8091389255691081711) -->
- <skip />
+ <string name="dream_overlay_status_bar_notification_indicator" msgid="8091389255691081711">"{count,plural, =1{# அறிவிப்பு}other{# அறிவிப்புகள்}}"</string>
</resources>
diff --git a/packages/SystemUI/res/values-te/strings.xml b/packages/SystemUI/res/values-te/strings.xml
index 6ef8f50..222da19 100644
--- a/packages/SystemUI/res/values-te/strings.xml
+++ b/packages/SystemUI/res/values-te/strings.xml
@@ -20,19 +20,17 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_label" msgid="4811759950673118541">"సిస్టమ్ UI"</string>
- <!-- no translation found for battery_low_title (5319680173344341779) -->
- <skip />
- <!-- no translation found for battery_low_description (3282977755476423966) -->
- <skip />
- <!-- no translation found for battery_low_intro (5148725009653088790) -->
- <skip />
+ <string name="battery_low_title" msgid="5319680173344341779">"బ్యాటరీ సేవర్ను ఆన్ చేయాలా?"</string>
+ <string name="battery_low_description" msgid="3282977755476423966">"మీకు <xliff:g id="PERCENTAGE">%s</xliff:g> బ్యాటరీ మిగిలి ఉంది. బ్యాటరీ సేవర్ ముదురు రంగు రూపాన్ని ఆన్ చేస్తుంది, బ్యాక్గ్రౌండ్ యాక్టివిటీని పరిమితం చేస్తుంది, అలాగే నోటిఫికేషన్లను ఆలస్యంగా పంపిస్తుంది."</string>
+ <string name="battery_low_intro" msgid="5148725009653088790">"బ్యాటరీ సేవర్ ముదురు రంగు రూపాన్ని ఆన్ చేస్తుంది, బ్యాక్గ్రౌండ్ యాక్టివిటీని పరిమితం చేస్తుంది, అలాగే నోటిఫికేషన్లను ఆలస్యంగా పంపిస్తుంది."</string>
<string name="battery_low_percent_format" msgid="4276661262843170964">"<xliff:g id="PERCENTAGE">%s</xliff:g> మిగిలి ఉంది"</string>
<string name="invalid_charger_title" msgid="938685362320735167">"USB ద్వారా ఛార్జ్ చేయలేరు"</string>
<string name="invalid_charger_text" msgid="2339310107232691577">"మీ పరికరంతో వచ్చిన ఛార్జర్ను ఉపయోగించండి"</string>
<string name="battery_saver_confirmation_title" msgid="1234998463717398453">"బ్యాటరీ సేవర్ను ఆన్ చేయాలా?"</string>
<string name="battery_saver_confirmation_title_generic" msgid="2299231884234959849">"బ్యాటరీ సేవర్ గురించి"</string>
<string name="battery_saver_confirmation_ok" msgid="5042136476802816494">"ఆన్ చేయి"</string>
- <string name="battery_saver_start_action" msgid="4553256017945469937">"బ్యాటరీ సేవర్ను ఆన్ చేయండి"</string>
+ <string name="battery_saver_start_action" msgid="8353766979886287140">"ఆన్ చేయండి"</string>
+ <string name="battery_saver_dismiss_action" msgid="7199342621040014738">"వద్దు, ధన్యవాదాలు"</string>
<string name="status_bar_settings_auto_rotation" msgid="8329080442278431708">"స్క్రీన్ ఆటో-రొటేట్"</string>
<string name="usb_device_permission_prompt" msgid="4414719028369181772">"<xliff:g id="USB_DEVICE">%2$s</xliff:g>ని యాక్సెస్ చేయడానికి <xliff:g id="APPLICATION">%1$s</xliff:g>ని అనుమతించాలా?"</string>
<string name="usb_device_permission_prompt_warn" msgid="2309129784984063656">"<xliff:g id="USB_DEVICE">%2$s</xliff:g>యాక్సెస్ చేయడానికి <xliff:g id="APPLICATION">%1$s</xliff:g>ను అనుమతించాలా?\nఈ యాప్నకు రికార్డ్ చేసే అనుమతి మంజూరు చేయబడలేదు, కానీ ఈ USB పరికరం ద్వారా ఆడియోను క్యాప్చర్ చేయగలదు."</string>
@@ -133,8 +131,7 @@
<string name="biometric_dialog_face_icon_description_authenticated" msgid="2242167416140740920">"ముఖం ప్రామాణీకరించబడింది"</string>
<string name="biometric_dialog_face_icon_description_confirmed" msgid="7918067993953940778">"నిర్ధారించబడింది"</string>
<string name="biometric_dialog_tap_confirm" msgid="9166350738859143358">"పూర్తి చేయడానికి \"నిర్ధారించు\" నొక్కండి"</string>
- <!-- no translation found for biometric_dialog_tap_confirm_with_face (1597899891472340950) -->
- <skip />
+ <string name="biometric_dialog_tap_confirm_with_face" msgid="1597899891472340950">"మీ ముఖం ద్వారా అన్లాక్ చేయబడింది. కొనసాగించడానికి నొక్కండి."</string>
<string name="biometric_dialog_authenticated" msgid="7337147327545272484">"ప్రామాణీకరించబడింది"</string>
<string name="biometric_dialog_use_pin" msgid="8385294115283000709">"పిన్ను ఉపయోగించు"</string>
<string name="biometric_dialog_use_pattern" msgid="2315593393167211194">"ఆకృతిని ఉపయోగించు"</string>
@@ -298,7 +295,7 @@
<string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"స్థూలదృష్టిని టోగుల్ చేయి"</string>
<string name="zen_priority_introduction" msgid="3159291973383796646">"మీరు పేర్కొనే అలారాలు, రిమైండర్లు, ఈవెంట్లు మరియు కాలర్ల నుండి మినహా మరే ఇతర ధ్వనులు మరియు వైబ్రేషన్లతో మీకు అంతరాయం కలగదు. మీరు ఇప్పటికీ సంగీతం, వీడియోలు మరియు గేమ్లతో సహా మీరు ప్లే చేయడానికి ఎంచుకున్నవి ఏవైనా వింటారు."</string>
<string name="zen_alarms_introduction" msgid="3987266042682300470">"అలారాలు నుండి మినహా మరే ఇతర ధ్వనులు మరియు వైబ్రేషన్లతో మీకు అంతరాయం కలగదు. మీరు ఇప్పటికీ సంగీతం, వీడియోలు మరియు గేమ్లతో సహా మీరు ప్లే చేయడానికి ఎంచుకున్నవి ఏవైనా వింటారు."</string>
- <string name="zen_priority_customize_button" msgid="4119213187257195047">"అనుకూలీకరించు"</string>
+ <string name="zen_priority_customize_button" msgid="4119213187257195047">"అనుకూలంగా మార్చండి"</string>
<string name="zen_silence_introduction_voice" msgid="853573681302712348">"ఇది అలారాలు, సంగీతం, వీడియోలు మరియు గేమ్లతో సహా అన్ని ధ్వనులు మరియు వైబ్రేషన్లను బ్లాక్ చేస్తుంది. మీరు ఇప్పటికీ ఫోన్ కాల్స్ చేయగలుగుతారు."</string>
<string name="zen_silence_introduction" msgid="6117517737057344014">"ఇది అలారాలు, సంగీతం, వీడియోలు మరియు గేమ్లతో సహా అన్ని ధ్వనులు మరియు వైబ్రేషన్లను బ్లాక్ చేస్తుంది."</string>
<string name="notification_tap_again" msgid="4477318164947497249">"తెరవడానికి మళ్లీ నొక్కండి"</string>
@@ -462,8 +459,8 @@
<string name="wallet_secondary_label_device_locked" msgid="5175862019125370506">"ఉపయోగించడానికి అన్లాక్ చేయండి"</string>
<string name="wallet_error_generic" msgid="257704570182963611">"మీ కార్డ్లను పొందడంలో సమస్య ఉంది, దయచేసి తర్వాత మళ్లీ ట్రై చేయండి"</string>
<string name="wallet_lockscreen_settings_label" msgid="3539105300870383570">"లాక్ స్క్రీన్ సెట్టింగ్లు"</string>
- <string name="qr_code_scanner_title" msgid="5660820608548306581">"QR కోడ్"</string>
- <string name="qr_code_scanner_description" msgid="7937603775306661863">"స్కాన్ చేయడానికి ట్యాప్ చేయండి"</string>
+ <!-- no translation found for qr_code_scanner_title (5290201053875420785) -->
+ <skip />
<string name="status_bar_work" msgid="5238641949837091056">"ఆఫీస్ ప్రొఫైల్"</string>
<string name="status_bar_airplane" msgid="4848702508684541009">"ఎయిర్ప్లేన్ మోడ్"</string>
<string name="zen_alarm_warning" msgid="7844303238486849503">"మీరు <xliff:g id="WHEN">%1$s</xliff:g> సెట్ చేసిన మీ తర్వాత అలారం మీకు వినిపించదు"</string>
@@ -827,6 +824,7 @@
<string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"కొత్త పరికరాన్ని పెయిర్ చేయండి"</string>
<string name="media_output_dialog_launch_app_text" msgid="1527413319632586259">"ఈ సెషన్ను ప్రసారం చేయడానికి, దయచేసి యాప్ను తెరవండి."</string>
<string name="media_output_dialog_unknown_launch_app_name" msgid="1084899329829371336">"తెలియని యాప్"</string>
+ <string name="media_output_dialog_button_stop_casting" msgid="6581379537930199189">"ప్రసారాన్ని ఆపివేయండి"</string>
<string name="build_number_clip_data_label" msgid="3623176728412560914">"బిల్డ్ నంబర్"</string>
<string name="build_number_copy_toast" msgid="877720921605503046">"బిల్డ్ నంబర్, క్లిప్బోర్డ్కు కాపీ చేయబడింది."</string>
<string name="basic_status" msgid="2315371112182658176">"సంభాషణను తెరవండి"</string>
@@ -916,7 +914,6 @@
<string name="dream_overlay_status_bar_wifi_off" msgid="4497069245055003582">"Wi‑Fi అందుబాటులో లేదు"</string>
<string name="dream_overlay_status_bar_priority_mode" msgid="5428462123314728739">"ముఖ్యమైన ఫైల్స్ మోడ్"</string>
<string name="dream_overlay_status_bar_alarm_set" msgid="566707328356590886">"అలారం సెట్ చేశాను"</string>
- <string name="dream_overlay_status_bar_assistant_guest_mode_enabled" msgid="3715897096012469615">"అసిస్టెంట్ గెస్ట్ మోడ్ ఎనేబుల్ చేయబడింది"</string>
<string name="dream_overlay_status_bar_camera_mic_off" msgid="3199425257833773569">"కెమెరా, మైక్ ఆఫ్లో ఉన్నాయి"</string>
<string name="dream_overlay_status_bar_notification_indicator" msgid="8091389255691081711">"{count,plural, =1{# నోటిఫికేషన్}other{# నోటిఫికేషన్లు}}"</string>
</resources>
diff --git a/packages/SystemUI/res/values-th/strings.xml b/packages/SystemUI/res/values-th/strings.xml
index 9072db4..120d870 100644
--- a/packages/SystemUI/res/values-th/strings.xml
+++ b/packages/SystemUI/res/values-th/strings.xml
@@ -20,19 +20,17 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_label" msgid="4811759950673118541">"อินเทอร์เฟซผู้ใช้ของระบบ"</string>
- <!-- no translation found for battery_low_title (5319680173344341779) -->
- <skip />
- <!-- no translation found for battery_low_description (3282977755476423966) -->
- <skip />
- <!-- no translation found for battery_low_intro (5148725009653088790) -->
- <skip />
+ <string name="battery_low_title" msgid="5319680173344341779">"เปิดโหมดประหยัดแบตเตอรี่ใช่ไหม"</string>
+ <string name="battery_low_description" msgid="3282977755476423966">"คุณมีแบตเตอรี่เหลืออยู่ <xliff:g id="PERCENTAGE">%s</xliff:g> โหมดประหยัดแบตเตอรี่จะเปิดธีมมืด จำกัดกิจกรรมในเบื้องหลัง และหน่วงเวลาการแจ้งเตือน"</string>
+ <string name="battery_low_intro" msgid="5148725009653088790">"โหมดประหยัดแบตเตอรี่จะเปิดธีมมืด จำกัดกิจกรรมในเบื้องหลัง และหน่วงเวลาการแจ้งเตือน"</string>
<string name="battery_low_percent_format" msgid="4276661262843170964">"เหลืออีก <xliff:g id="PERCENTAGE">%s</xliff:g>"</string>
<string name="invalid_charger_title" msgid="938685362320735167">"ชาร์จผ่าน USB ไม่ได้"</string>
<string name="invalid_charger_text" msgid="2339310107232691577">"ใช้ที่ชาร์จที่ให้มาพร้อมกับอุปกรณ์"</string>
<string name="battery_saver_confirmation_title" msgid="1234998463717398453">"เปิดโหมดประหยัดแบตเตอรี่ใช่ไหม"</string>
<string name="battery_saver_confirmation_title_generic" msgid="2299231884234959849">"เกี่ยวกับโหมดประหยัดแบตเตอรี่"</string>
<string name="battery_saver_confirmation_ok" msgid="5042136476802816494">"เปิด"</string>
- <string name="battery_saver_start_action" msgid="4553256017945469937">"เปิดโหมดประหยัดแบตเตอรี่"</string>
+ <string name="battery_saver_start_action" msgid="8353766979886287140">"เปิด"</string>
+ <string name="battery_saver_dismiss_action" msgid="7199342621040014738">"ไม่เป็นไร"</string>
<string name="status_bar_settings_auto_rotation" msgid="8329080442278431708">"หมุนหน้าจออัตโนมัติ"</string>
<string name="usb_device_permission_prompt" msgid="4414719028369181772">"อนุญาตให้ <xliff:g id="APPLICATION">%1$s</xliff:g> เข้าถึง <xliff:g id="USB_DEVICE">%2$s</xliff:g> ไหม"</string>
<string name="usb_device_permission_prompt_warn" msgid="2309129784984063656">"อนุญาตให้ <xliff:g id="APPLICATION">%1$s</xliff:g> เข้าถึง <xliff:g id="USB_DEVICE">%2$s</xliff:g> ไหม\nแอปนี้ไม่ได้รับอนุญาตให้อัดเสียงแต่จะอัดเสียงผ่านอุปกรณ์ USB นี้ได้"</string>
@@ -133,8 +131,7 @@
<string name="biometric_dialog_face_icon_description_authenticated" msgid="2242167416140740920">"ตรวจสอบสิทธิ์ใบหน้าแล้ว"</string>
<string name="biometric_dialog_face_icon_description_confirmed" msgid="7918067993953940778">"ยืนยันแล้ว"</string>
<string name="biometric_dialog_tap_confirm" msgid="9166350738859143358">"แตะยืนยันเพื่อดำเนินการให้เสร็จสมบูรณ์"</string>
- <!-- no translation found for biometric_dialog_tap_confirm_with_face (1597899891472340950) -->
- <skip />
+ <string name="biometric_dialog_tap_confirm_with_face" msgid="1597899891472340950">"ปลดล็อกโดยใช้ใบหน้าแล้ว กดเพื่อดำเนินการต่อ"</string>
<string name="biometric_dialog_authenticated" msgid="7337147327545272484">"ตรวจสอบสิทธิ์แล้ว"</string>
<string name="biometric_dialog_use_pin" msgid="8385294115283000709">"ใช้ PIN"</string>
<string name="biometric_dialog_use_pattern" msgid="2315593393167211194">"ใช้รูปแบบ"</string>
@@ -462,8 +459,8 @@
<string name="wallet_secondary_label_device_locked" msgid="5175862019125370506">"ปลดล็อกเพื่อใช้"</string>
<string name="wallet_error_generic" msgid="257704570182963611">"เกิดปัญหาในการดึงข้อมูลบัตรของคุณ โปรดลองอีกครั้งในภายหลัง"</string>
<string name="wallet_lockscreen_settings_label" msgid="3539105300870383570">"การตั้งค่าหน้าจอล็อก"</string>
- <string name="qr_code_scanner_title" msgid="5660820608548306581">"คิวอาร์โค้ด"</string>
- <string name="qr_code_scanner_description" msgid="7937603775306661863">"แตะเพื่อสแกน"</string>
+ <!-- no translation found for qr_code_scanner_title (5290201053875420785) -->
+ <skip />
<string name="status_bar_work" msgid="5238641949837091056">"โปรไฟล์งาน"</string>
<string name="status_bar_airplane" msgid="4848702508684541009">"โหมดบนเครื่องบิน"</string>
<string name="zen_alarm_warning" msgid="7844303238486849503">"คุณจะไม่ได้ยินเสียงปลุกครั้งถัดไปในเวลา <xliff:g id="WHEN">%1$s</xliff:g>"</string>
@@ -827,6 +824,7 @@
<string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"จับคู่อุปกรณ์ใหม่"</string>
<string name="media_output_dialog_launch_app_text" msgid="1527413319632586259">"โปรดเปิดแอปหากต้องการแคสต์เซสชันนี้"</string>
<string name="media_output_dialog_unknown_launch_app_name" msgid="1084899329829371336">"แอปที่ไม่รู้จัก"</string>
+ <string name="media_output_dialog_button_stop_casting" msgid="6581379537930199189">"หยุดแคสต์"</string>
<string name="build_number_clip_data_label" msgid="3623176728412560914">"หมายเลขบิลด์"</string>
<string name="build_number_copy_toast" msgid="877720921605503046">"คัดลอกหมายเลขบิลด์ไปยังคลิปบอร์ดแล้ว"</string>
<string name="basic_status" msgid="2315371112182658176">"เปิดการสนทนา"</string>
@@ -889,7 +887,7 @@
<string name="wifi_wont_autoconnect_for_now" msgid="5782282612749867762">"Wi-Fi จะไม่เชื่อมต่ออัตโนมัติในตอนนี้"</string>
<string name="see_all_networks" msgid="3773666844913168122">"ดูทั้งหมด"</string>
<string name="to_switch_networks_disconnect_ethernet" msgid="6698111101156951955">"ตัดการเชื่อมต่ออีเทอร์เน็ตเพื่อสลับเครือข่าย"</string>
- <string name="wifi_scan_notify_message" msgid="3753839537448621794">"เพื่อปรับปรุงประสบการณ์การใช้อุปกรณ์ แอปและบริการต่างๆ จะยังคงสแกนหาเครือข่าย Wi‑Fi ได้ทุกเมื่อแม้ว่า Wi‑Fi จะปิดอยู่ คุณเปลี่ยนตัวเลือกนี้ได้ในการตั้งค่าการสแกนหา Wi-Fi "<annotation id="link">"เปลี่ยน"</annotation></string>
+ <string name="wifi_scan_notify_message" msgid="3753839537448621794">"เพื่อปรับปรุงประสบการณ์การใช้อุปกรณ์ แอปและบริการต่างๆ จะยังคงสแกนหาเครือข่าย Wi‑Fi ได้ทุกเมื่อแม้ว่า Wi‑Fi จะปิดอยู่ คุณเปลี่ยนตัวเลือกนี้ได้ในการตั้งค่าการสแกนหา Wi-Fi "<annotation id="link">"เปลี่ยนการตั้งค่า"</annotation></string>
<string name="turn_off_airplane_mode" msgid="8425587763226548579">"ปิดโหมดบนเครื่องบิน"</string>
<string name="qs_tile_request_dialog_text" msgid="3501359944139877694">"<xliff:g id="APPNAME">%1$s</xliff:g> ต้องการเพิ่มชิ้นส่วนต่อไปนี้ในการตั้งค่าด่วน"</string>
<string name="qs_tile_request_dialog_add" msgid="4888460910694986304">"เพิ่มชิ้นส่วน"</string>
@@ -916,7 +914,6 @@
<string name="dream_overlay_status_bar_wifi_off" msgid="4497069245055003582">"ใช้ Wi‑Fi ไม่ได้"</string>
<string name="dream_overlay_status_bar_priority_mode" msgid="5428462123314728739">"โหมดลำดับความสำคัญ"</string>
<string name="dream_overlay_status_bar_alarm_set" msgid="566707328356590886">"ตั้งปลุกแล้ว"</string>
- <string name="dream_overlay_status_bar_assistant_guest_mode_enabled" msgid="3715897096012469615">"เปิดใช้โหมดผู้มาเยือนของ Assistant แล้ว"</string>
<string name="dream_overlay_status_bar_camera_mic_off" msgid="3199425257833773569">"กล้องและไมค์ปิดอยู่"</string>
<string name="dream_overlay_status_bar_notification_indicator" msgid="8091389255691081711">"{count,plural, =1{การแจ้งเตือน # รายการ}other{การแจ้งเตือน # รายการ}}"</string>
</resources>
diff --git a/packages/SystemUI/res/values-tl/strings.xml b/packages/SystemUI/res/values-tl/strings.xml
index b518c60..4d5655c 100644
--- a/packages/SystemUI/res/values-tl/strings.xml
+++ b/packages/SystemUI/res/values-tl/strings.xml
@@ -20,19 +20,17 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_label" msgid="4811759950673118541">"UI ng System"</string>
- <!-- no translation found for battery_low_title (5319680173344341779) -->
- <skip />
- <!-- no translation found for battery_low_description (3282977755476423966) -->
- <skip />
- <!-- no translation found for battery_low_intro (5148725009653088790) -->
- <skip />
+ <string name="battery_low_title" msgid="5319680173344341779">"I-on ang Pantipid ng Baterya?"</string>
+ <string name="battery_low_description" msgid="3282977755476423966">"<xliff:g id="PERCENTAGE">%s</xliff:g> na lang ang natitira sa iyong baterya. Ino-on ng Pantipid ng Baterya ang Madilim na tema, pinaghihigpitan nito ang aktibidad sa background, at inaantala nito ang mga notification."</string>
+ <string name="battery_low_intro" msgid="5148725009653088790">"Ino-on ng Pantipid ng Baterya ang Madilim na tema, pinaghihigpitan nito ang aktibidad sa background, at inaantala nito ang mga notification."</string>
<string name="battery_low_percent_format" msgid="4276661262843170964">"<xliff:g id="PERCENTAGE">%s</xliff:g> na lang ang natitira"</string>
<string name="invalid_charger_title" msgid="938685362320735167">"Hindi makapag-charge sa pamamagitan ng USB"</string>
<string name="invalid_charger_text" msgid="2339310107232691577">"Gamitin ang charger na kasama ng iyong device"</string>
<string name="battery_saver_confirmation_title" msgid="1234998463717398453">"I-on ang Pantipid ng Baterya?"</string>
<string name="battery_saver_confirmation_title_generic" msgid="2299231884234959849">"Tungkol sa Pantipid ng Baterya"</string>
<string name="battery_saver_confirmation_ok" msgid="5042136476802816494">"I-on"</string>
- <string name="battery_saver_start_action" msgid="4553256017945469937">"I-on ang Pantipid ng Baterya"</string>
+ <string name="battery_saver_start_action" msgid="8353766979886287140">"I-on"</string>
+ <string name="battery_saver_dismiss_action" msgid="7199342621040014738">"Huwag na lang"</string>
<string name="status_bar_settings_auto_rotation" msgid="8329080442278431708">"I-auto rotate ang screen"</string>
<string name="usb_device_permission_prompt" msgid="4414719028369181772">"Payagan ang <xliff:g id="APPLICATION">%1$s</xliff:g> na ma-access ang <xliff:g id="USB_DEVICE">%2$s</xliff:g>?"</string>
<string name="usb_device_permission_prompt_warn" msgid="2309129784984063656">"Payagan ang <xliff:g id="APPLICATION">%1$s</xliff:g> na i-access ang <xliff:g id="USB_DEVICE">%2$s</xliff:g>?\nHindi nabigyan ng pahintulot ang app na ito para mag-record pero nakakapag-capture ito ng audio sa pamamagitan ng USB device na ito."</string>
@@ -133,8 +131,7 @@
<string name="biometric_dialog_face_icon_description_authenticated" msgid="2242167416140740920">"Na-authenticate ang mukha"</string>
<string name="biometric_dialog_face_icon_description_confirmed" msgid="7918067993953940778">"Nakumpirma"</string>
<string name="biometric_dialog_tap_confirm" msgid="9166350738859143358">"I-tap ang Kumpirmahin para kumpletuhin"</string>
- <!-- no translation found for biometric_dialog_tap_confirm_with_face (1597899891472340950) -->
- <skip />
+ <string name="biometric_dialog_tap_confirm_with_face" msgid="1597899891472340950">"Na-unlock gamit ang mukha mo. Pindutin para magpatuloy."</string>
<string name="biometric_dialog_authenticated" msgid="7337147327545272484">"Na-authenticate"</string>
<string name="biometric_dialog_use_pin" msgid="8385294115283000709">"Gumamit ng PIN"</string>
<string name="biometric_dialog_use_pattern" msgid="2315593393167211194">"Gumamit ng pattern"</string>
@@ -462,8 +459,8 @@
<string name="wallet_secondary_label_device_locked" msgid="5175862019125370506">"I-unlock para magamit"</string>
<string name="wallet_error_generic" msgid="257704570182963611">"Nagkaproblema sa pagkuha ng iyong mga card, pakisubukan ulit sa ibang pagkakataon"</string>
<string name="wallet_lockscreen_settings_label" msgid="3539105300870383570">"Mga setting ng lock screen"</string>
- <string name="qr_code_scanner_title" msgid="5660820608548306581">"QR code"</string>
- <string name="qr_code_scanner_description" msgid="7937603775306661863">"I-tap para i-scan"</string>
+ <!-- no translation found for qr_code_scanner_title (5290201053875420785) -->
+ <skip />
<string name="status_bar_work" msgid="5238641949837091056">"Profile sa trabaho"</string>
<string name="status_bar_airplane" msgid="4848702508684541009">"Airplane mode"</string>
<string name="zen_alarm_warning" msgid="7844303238486849503">"Hindi mo maririnig ang iyong susunod na alarm ng <xliff:g id="WHEN">%1$s</xliff:g>"</string>
@@ -827,6 +824,7 @@
<string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"Magpares ng bagong device"</string>
<string name="media_output_dialog_launch_app_text" msgid="1527413319632586259">"Para ma-cast ang session na ito, buksan ang app."</string>
<string name="media_output_dialog_unknown_launch_app_name" msgid="1084899329829371336">"Hindi kilalang app"</string>
+ <string name="media_output_dialog_button_stop_casting" msgid="6581379537930199189">"Ihinto ang pag-cast"</string>
<string name="build_number_clip_data_label" msgid="3623176728412560914">"Numero ng build"</string>
<string name="build_number_copy_toast" msgid="877720921605503046">"Nakopya sa clipboard ang numero ng build."</string>
<string name="basic_status" msgid="2315371112182658176">"Buksan ang pag-uusap"</string>
@@ -916,7 +914,6 @@
<string name="dream_overlay_status_bar_wifi_off" msgid="4497069245055003582">"Hindi available ang Wi‑Fi"</string>
<string name="dream_overlay_status_bar_priority_mode" msgid="5428462123314728739">"Priority mode"</string>
<string name="dream_overlay_status_bar_alarm_set" msgid="566707328356590886">"Nakatakda ang alarm"</string>
- <string name="dream_overlay_status_bar_assistant_guest_mode_enabled" msgid="3715897096012469615">"Naka-enable ang guest mode ng Assistant"</string>
<string name="dream_overlay_status_bar_camera_mic_off" msgid="3199425257833773569">"Naka-off ang camera at mikropono"</string>
<string name="dream_overlay_status_bar_notification_indicator" msgid="8091389255691081711">"{count,plural, =1{# notification}one{# notification}other{# na notification}}"</string>
</resources>
diff --git a/packages/SystemUI/res/values-tr/strings.xml b/packages/SystemUI/res/values-tr/strings.xml
index 0f56057..170d582 100644
--- a/packages/SystemUI/res/values-tr/strings.xml
+++ b/packages/SystemUI/res/values-tr/strings.xml
@@ -20,19 +20,17 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_label" msgid="4811759950673118541">"Sistem Arayüzü"</string>
- <!-- no translation found for battery_low_title (5319680173344341779) -->
- <skip />
- <!-- no translation found for battery_low_description (3282977755476423966) -->
- <skip />
- <!-- no translation found for battery_low_intro (5148725009653088790) -->
- <skip />
+ <string name="battery_low_title" msgid="5319680173344341779">"Pil Tasarrufu açılsın mı?"</string>
+ <string name="battery_low_description" msgid="3282977755476423966">"<xliff:g id="PERCENTAGE">%s</xliff:g> piliniz kaldı. Pil Tasarrufu, koyu temayı açıp arka plan etkinliğini kısıtlar ve bildirimleri geciktirir."</string>
+ <string name="battery_low_intro" msgid="5148725009653088790">"Pil Tasarrufu, koyu temayı açıp arka plan etkinliğini kısıtlar ve bildirimleri geciktirir."</string>
<string name="battery_low_percent_format" msgid="4276661262843170964">"<xliff:g id="PERCENTAGE">%s</xliff:g> kaldı"</string>
<string name="invalid_charger_title" msgid="938685362320735167">"USB ile şarj edilemiyor"</string>
<string name="invalid_charger_text" msgid="2339310107232691577">"Cihazınızla birlikte gelen şarj cihazını kullanın"</string>
<string name="battery_saver_confirmation_title" msgid="1234998463717398453">"Pil Tasarrufu açılsın mı?"</string>
<string name="battery_saver_confirmation_title_generic" msgid="2299231884234959849">"Pil Tasarrufu hakkında"</string>
<string name="battery_saver_confirmation_ok" msgid="5042136476802816494">"Aç"</string>
- <string name="battery_saver_start_action" msgid="4553256017945469937">"Pil Tasarrufu\'nu aç"</string>
+ <string name="battery_saver_start_action" msgid="8353766979886287140">"Aç"</string>
+ <string name="battery_saver_dismiss_action" msgid="7199342621040014738">"Hayır, teşekkürler"</string>
<string name="status_bar_settings_auto_rotation" msgid="8329080442278431708">"Ekranı otomatik döndür"</string>
<string name="usb_device_permission_prompt" msgid="4414719028369181772">"<xliff:g id="APPLICATION">%1$s</xliff:g> uygulamasının <xliff:g id="USB_DEVICE">%2$s</xliff:g> cihazına erişmesine izin verilsin mi?"</string>
<string name="usb_device_permission_prompt_warn" msgid="2309129784984063656">"<xliff:g id="APPLICATION">%1$s</xliff:g> uygulamasının <xliff:g id="USB_DEVICE">%2$s</xliff:g> cihazına erişmesine izin verilsin mi?\nBu uygulamaya kayıt izni verilmemiş ancak bu USB cihazı aracılığıyla sesleri yakalayabilir."</string>
@@ -133,8 +131,7 @@
<string name="biometric_dialog_face_icon_description_authenticated" msgid="2242167416140740920">"Yüz kimliği doğrulandı"</string>
<string name="biometric_dialog_face_icon_description_confirmed" msgid="7918067993953940778">"Onaylandı"</string>
<string name="biometric_dialog_tap_confirm" msgid="9166350738859143358">"Tamamlamak için Onayla\'ya dokunun"</string>
- <!-- no translation found for biometric_dialog_tap_confirm_with_face (1597899891472340950) -->
- <skip />
+ <string name="biometric_dialog_tap_confirm_with_face" msgid="1597899891472340950">"Kilit, yüzünüzle açıldı. Devam etmek için basın."</string>
<string name="biometric_dialog_authenticated" msgid="7337147327545272484">"Kimliği Doğrulandı"</string>
<string name="biometric_dialog_use_pin" msgid="8385294115283000709">"PIN kullan"</string>
<string name="biometric_dialog_use_pattern" msgid="2315593393167211194">"Deseni kullan"</string>
@@ -462,8 +459,8 @@
<string name="wallet_secondary_label_device_locked" msgid="5175862019125370506">"Kullanmak için kilidi aç"</string>
<string name="wallet_error_generic" msgid="257704570182963611">"Kartlarınız alınırken bir sorun oluştu. Lütfen daha sonra tekrar deneyin"</string>
<string name="wallet_lockscreen_settings_label" msgid="3539105300870383570">"Kilit ekranı ayarları"</string>
- <string name="qr_code_scanner_title" msgid="5660820608548306581">"QR kodu"</string>
- <string name="qr_code_scanner_description" msgid="7937603775306661863">"Taramak için dokunun"</string>
+ <!-- no translation found for qr_code_scanner_title (5290201053875420785) -->
+ <skip />
<string name="status_bar_work" msgid="5238641949837091056">"İş profili"</string>
<string name="status_bar_airplane" msgid="4848702508684541009">"Uçak modu"</string>
<string name="zen_alarm_warning" msgid="7844303238486849503">"<xliff:g id="WHEN">%1$s</xliff:g> olarak ayarlanmış bir sonraki alarmınızı duymayacaksınız"</string>
@@ -827,6 +824,7 @@
<string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"Yeni cihaz eşle"</string>
<string name="media_output_dialog_launch_app_text" msgid="1527413319632586259">"Bu oturumu yayınlamak için lütfen uygulamayı açın."</string>
<string name="media_output_dialog_unknown_launch_app_name" msgid="1084899329829371336">"Bilinmeyen uygulama"</string>
+ <string name="media_output_dialog_button_stop_casting" msgid="6581379537930199189">"Yayını durdur"</string>
<string name="build_number_clip_data_label" msgid="3623176728412560914">"Derleme numarası"</string>
<string name="build_number_copy_toast" msgid="877720921605503046">"Derleme numarası panoya kopyalandı."</string>
<string name="basic_status" msgid="2315371112182658176">"Görüşmeyi aç"</string>
@@ -916,8 +914,6 @@
<string name="dream_overlay_status_bar_wifi_off" msgid="4497069245055003582">"Kablosuz kullanılamıyor"</string>
<string name="dream_overlay_status_bar_priority_mode" msgid="5428462123314728739">"Öncelik modu"</string>
<string name="dream_overlay_status_bar_alarm_set" msgid="566707328356590886">"Alarm kuruldu"</string>
- <string name="dream_overlay_status_bar_assistant_guest_mode_enabled" msgid="3715897096012469615">"Asistan misafir modu etkinleştirildi"</string>
<string name="dream_overlay_status_bar_camera_mic_off" msgid="3199425257833773569">"Kamera ve mikrofon kapalı"</string>
- <!-- no translation found for dream_overlay_status_bar_notification_indicator (8091389255691081711) -->
- <skip />
+ <string name="dream_overlay_status_bar_notification_indicator" msgid="8091389255691081711">"{count,plural, =1{# bildirim}other{# bildirim}}"</string>
</resources>
diff --git a/packages/SystemUI/res/values-uk/strings.xml b/packages/SystemUI/res/values-uk/strings.xml
index fa9af2e..87ea462 100644
--- a/packages/SystemUI/res/values-uk/strings.xml
+++ b/packages/SystemUI/res/values-uk/strings.xml
@@ -20,19 +20,17 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_label" msgid="4811759950673118541">"Інтерфейс системи"</string>
- <!-- no translation found for battery_low_title (5319680173344341779) -->
- <skip />
- <!-- no translation found for battery_low_description (3282977755476423966) -->
- <skip />
- <!-- no translation found for battery_low_intro (5148725009653088790) -->
- <skip />
+ <string name="battery_low_title" msgid="5319680173344341779">"Увімкнути режим енергозбереження?"</string>
+ <string name="battery_low_description" msgid="3282977755476423966">"У вас залишилося <xliff:g id="PERCENTAGE">%s</xliff:g> заряду акумулятора. У режимі енергозбереження вмикається Темна тема, обмежуються дії у фоновому режимі та затримуються сповіщення."</string>
+ <string name="battery_low_intro" msgid="5148725009653088790">"У режимі енергозбереження вмикається Темна тема, обмежуються дії у фоновому режимі та затримуються сповіщення."</string>
<string name="battery_low_percent_format" msgid="4276661262843170964">"Залишилося <xliff:g id="PERCENTAGE">%s</xliff:g>"</string>
<string name="invalid_charger_title" msgid="938685362320735167">"Не вдається зарядити через USB"</string>
<string name="invalid_charger_text" msgid="2339310107232691577">"Використовуйте зарядний пристрій, який входить у комплект пристрою"</string>
<string name="battery_saver_confirmation_title" msgid="1234998463717398453">"Увімкнути режим енергозбереження?"</string>
<string name="battery_saver_confirmation_title_generic" msgid="2299231884234959849">"Про режим енергозбереження"</string>
<string name="battery_saver_confirmation_ok" msgid="5042136476802816494">"Увімкнути"</string>
- <string name="battery_saver_start_action" msgid="4553256017945469937">"Увімкнути режим енергозбереження"</string>
+ <string name="battery_saver_start_action" msgid="8353766979886287140">"Увімкнути"</string>
+ <string name="battery_saver_dismiss_action" msgid="7199342621040014738">"Ні, дякую"</string>
<string name="status_bar_settings_auto_rotation" msgid="8329080442278431708">"Автообертання екрана"</string>
<string name="usb_device_permission_prompt" msgid="4414719028369181772">"Надати додатку <xliff:g id="APPLICATION">%1$s</xliff:g> доступ до такого аксесуара: <xliff:g id="USB_DEVICE">%2$s</xliff:g>?"</string>
<string name="usb_device_permission_prompt_warn" msgid="2309129784984063656">"Надати додатку <xliff:g id="APPLICATION">%1$s</xliff:g> доступ до <xliff:g id="USB_DEVICE">%2$s</xliff:g>?\nЦей додаток не має дозволу на записування звуку, але може фіксувати його через цей USB-пристрій."</string>
@@ -133,8 +131,7 @@
<string name="biometric_dialog_face_icon_description_authenticated" msgid="2242167416140740920">"Обличчя автентифіковано"</string>
<string name="biometric_dialog_face_icon_description_confirmed" msgid="7918067993953940778">"Підтверджено"</string>
<string name="biometric_dialog_tap_confirm" msgid="9166350738859143358">"Щоб завершити, натисніть \"Підтвердити\""</string>
- <!-- no translation found for biometric_dialog_tap_confirm_with_face (1597899891472340950) -->
- <skip />
+ <string name="biometric_dialog_tap_confirm_with_face" msgid="1597899891472340950">"Розблоковано: фейсконтроль. Натисніть, щоб продовжити."</string>
<string name="biometric_dialog_authenticated" msgid="7337147327545272484">"Автентифіковано"</string>
<string name="biometric_dialog_use_pin" msgid="8385294115283000709">"Ввести PIN-код"</string>
<string name="biometric_dialog_use_pattern" msgid="2315593393167211194">"Намалювати ключ"</string>
@@ -468,8 +465,8 @@
<string name="wallet_secondary_label_device_locked" msgid="5175862019125370506">"Розблокувати, щоб використовувати"</string>
<string name="wallet_error_generic" msgid="257704570182963611">"Не вдалось отримати ваші картки. Повторіть спробу пізніше."</string>
<string name="wallet_lockscreen_settings_label" msgid="3539105300870383570">"Параметри блокування екрана"</string>
- <string name="qr_code_scanner_title" msgid="5660820608548306581">"QR-код"</string>
- <string name="qr_code_scanner_description" msgid="7937603775306661863">"Натисніть, щоб сканувати"</string>
+ <!-- no translation found for qr_code_scanner_title (5290201053875420785) -->
+ <skip />
<string name="status_bar_work" msgid="5238641949837091056">"Робочий профіль"</string>
<string name="status_bar_airplane" msgid="4848702508684541009">"Режим польоту"</string>
<string name="zen_alarm_warning" msgid="7844303238486849503">"Наступний сигнал о <xliff:g id="WHEN">%1$s</xliff:g> не пролунає"</string>
@@ -839,6 +836,7 @@
<string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"Підключити новий пристрій"</string>
<string name="media_output_dialog_launch_app_text" msgid="1527413319632586259">"Щоб транслювати цей сеанс, відкрийте додаток."</string>
<string name="media_output_dialog_unknown_launch_app_name" msgid="1084899329829371336">"Невідомий додаток"</string>
+ <string name="media_output_dialog_button_stop_casting" msgid="6581379537930199189">"Припинити трансляцію"</string>
<string name="build_number_clip_data_label" msgid="3623176728412560914">"Номер складання"</string>
<string name="build_number_copy_toast" msgid="877720921605503046">"Номер складання скопійовано в буфер обміну."</string>
<string name="basic_status" msgid="2315371112182658176">"Відкрита розмова"</string>
@@ -930,8 +928,6 @@
<string name="dream_overlay_status_bar_wifi_off" msgid="4497069245055003582">"Мережа Wi-Fi недоступна"</string>
<string name="dream_overlay_status_bar_priority_mode" msgid="5428462123314728739">"Режим пріоритету"</string>
<string name="dream_overlay_status_bar_alarm_set" msgid="566707328356590886">"Будильник установлено"</string>
- <string name="dream_overlay_status_bar_assistant_guest_mode_enabled" msgid="3715897096012469615">"Увімкнено режим гостя Асистента"</string>
<string name="dream_overlay_status_bar_camera_mic_off" msgid="3199425257833773569">"Камеру й мікрофон вимкнено"</string>
- <!-- no translation found for dream_overlay_status_bar_notification_indicator (8091389255691081711) -->
- <skip />
+ <string name="dream_overlay_status_bar_notification_indicator" msgid="8091389255691081711">"{count,plural, =1{# сповіщення}one{# сповіщення}few{# сповіщення}many{# сповіщень}other{# сповіщення}}"</string>
</resources>
diff --git a/packages/SystemUI/res/values-ur/strings.xml b/packages/SystemUI/res/values-ur/strings.xml
index 3576021..cb1cbdd 100644
--- a/packages/SystemUI/res/values-ur/strings.xml
+++ b/packages/SystemUI/res/values-ur/strings.xml
@@ -20,19 +20,17 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_label" msgid="4811759950673118541">"سسٹم UI"</string>
- <!-- no translation found for battery_low_title (5319680173344341779) -->
- <skip />
- <!-- no translation found for battery_low_description (3282977755476423966) -->
- <skip />
- <!-- no translation found for battery_low_intro (5148725009653088790) -->
- <skip />
+ <string name="battery_low_title" msgid="5319680173344341779">"بیٹری سیور آن کریں؟"</string>
+ <string name="battery_low_description" msgid="3282977755476423966">"آپ کے پاس <xliff:g id="PERCENTAGE">%s</xliff:g> بیٹری باقی ہے۔ بیٹری سیور گہری تھیم کو آن، پس منظر کی سرگرمی کو محدود اور اطلاعات میں تاخیر کرتی ہے۔"</string>
+ <string name="battery_low_intro" msgid="5148725009653088790">"بیٹری سیور گہری تھیم کو آن، پس منظر کی سرگرمی کو محدود اور اطلاعات میں تاخیر کرتی ہے۔"</string>
<string name="battery_low_percent_format" msgid="4276661262843170964">"<xliff:g id="PERCENTAGE">%s</xliff:g> باقی ہے"</string>
<string name="invalid_charger_title" msgid="938685362320735167">"USB کے ذریعے چارج نہیں کر سکتے"</string>
<string name="invalid_charger_text" msgid="2339310107232691577">"اپنے آلہ کے ساتھ ملنے والے چارجر کا استعمال کریں"</string>
<string name="battery_saver_confirmation_title" msgid="1234998463717398453">"بیٹری سیور آن کریں؟"</string>
<string name="battery_saver_confirmation_title_generic" msgid="2299231884234959849">"بیٹری سیور کے بارے میں"</string>
<string name="battery_saver_confirmation_ok" msgid="5042136476802816494">"آن کریں"</string>
- <string name="battery_saver_start_action" msgid="4553256017945469937">"بیٹری سیور آن کریں"</string>
+ <string name="battery_saver_start_action" msgid="8353766979886287140">"آن کریں"</string>
+ <string name="battery_saver_dismiss_action" msgid="7199342621040014738">"نہیں شکریہ"</string>
<string name="status_bar_settings_auto_rotation" msgid="8329080442278431708">"سکرین کو خودکار طور پر گھمائیں"</string>
<string name="usb_device_permission_prompt" msgid="4414719028369181772">"<xliff:g id="APPLICATION">%1$s</xliff:g> کو <xliff:g id="USB_DEVICE">%2$s</xliff:g> تک رسائی حاصل کرنے کی اجازت دیں؟"</string>
<string name="usb_device_permission_prompt_warn" msgid="2309129784984063656">"<xliff:g id="APPLICATION">%1$s</xliff:g> کو <xliff:g id="USB_DEVICE">%2$s</xliff:g> تک رسائی دیں؟\nاس ایپ کو ریکارڈ کی اجازت عطا نہیں کی گئی ہے مگر اس USB آلہ سے کیپچر کر سکتے ہیں۔"</string>
@@ -133,8 +131,7 @@
<string name="biometric_dialog_face_icon_description_authenticated" msgid="2242167416140740920">"چہرے کی تصدیق ہو گئی"</string>
<string name="biometric_dialog_face_icon_description_confirmed" msgid="7918067993953940778">"تصدیق شدہ"</string>
<string name="biometric_dialog_tap_confirm" msgid="9166350738859143358">"مکمل کرنے کیلئے \'تصدیق کریں\' تھپتھپائیں"</string>
- <!-- no translation found for biometric_dialog_tap_confirm_with_face (1597899891472340950) -->
- <skip />
+ <string name="biometric_dialog_tap_confirm_with_face" msgid="1597899891472340950">"آپ کے چہرے سے غیر مقفل کیا گیا جاری رکھنے کے لیے دبائیں"</string>
<string name="biometric_dialog_authenticated" msgid="7337147327545272484">"تصدیق کردہ"</string>
<string name="biometric_dialog_use_pin" msgid="8385294115283000709">"PIN استعمال کریں"</string>
<string name="biometric_dialog_use_pattern" msgid="2315593393167211194">"پیٹرن کا استعمال کریں"</string>
@@ -462,8 +459,8 @@
<string name="wallet_secondary_label_device_locked" msgid="5175862019125370506">"استعمال کرنے کے لیے غیر مقفل کریں"</string>
<string name="wallet_error_generic" msgid="257704570182963611">"آپ کے کارڈز حاصل کرنے میں ایک مسئلہ درپیش تھا، براہ کرم بعد میں دوبارہ کوشش کریں"</string>
<string name="wallet_lockscreen_settings_label" msgid="3539105300870383570">"مقفل اسکرین کی ترتیبات"</string>
- <string name="qr_code_scanner_title" msgid="5660820608548306581">"QR کوڈ"</string>
- <string name="qr_code_scanner_description" msgid="7937603775306661863">"اسکین کرنے کے لیے تھپتھپائیں"</string>
+ <!-- no translation found for qr_code_scanner_title (5290201053875420785) -->
+ <skip />
<string name="status_bar_work" msgid="5238641949837091056">"دفتری پروفائل"</string>
<string name="status_bar_airplane" msgid="4848702508684541009">"ہوائی جہاز وضع"</string>
<string name="zen_alarm_warning" msgid="7844303238486849503">"آپ کو <xliff:g id="WHEN">%1$s</xliff:g> بجے اپنا اگلا الارم سنائی نہیں دے گا"</string>
@@ -827,6 +824,7 @@
<string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"نئے آلہ کا جوڑا بنائیں"</string>
<string name="media_output_dialog_launch_app_text" msgid="1527413319632586259">"اس سیشن کو کاسٹ کرنے کیلئے، براہ کرم ایپ کھولیں۔"</string>
<string name="media_output_dialog_unknown_launch_app_name" msgid="1084899329829371336">"نامعلوم ایپ"</string>
+ <string name="media_output_dialog_button_stop_casting" msgid="6581379537930199189">"کاسٹ کرنا بند کریں"</string>
<string name="build_number_clip_data_label" msgid="3623176728412560914">"بلڈ نمبر"</string>
<string name="build_number_copy_toast" msgid="877720921605503046">"بلڈ نمبر کلپ بورڈ میں کاپی ہو گیا۔"</string>
<string name="basic_status" msgid="2315371112182658176">"گفتگو کھولیں"</string>
@@ -916,7 +914,6 @@
<string name="dream_overlay_status_bar_wifi_off" msgid="4497069245055003582">"Wi-Fi دستیاب نہیں ہے"</string>
<string name="dream_overlay_status_bar_priority_mode" msgid="5428462123314728739">"ترجیحی وضع"</string>
<string name="dream_overlay_status_bar_alarm_set" msgid="566707328356590886">"الارم سیٹ ہوگیا"</string>
- <string name="dream_overlay_status_bar_assistant_guest_mode_enabled" msgid="3715897096012469615">"اسسٹنٹ مہمان وضع فعال ہے"</string>
<string name="dream_overlay_status_bar_camera_mic_off" msgid="3199425257833773569">"کیمرا اور مائیک آف ہیں"</string>
<string name="dream_overlay_status_bar_notification_indicator" msgid="8091389255691081711">"{count,plural, =1{# اطلاع}other{# اطلاعات}}"</string>
</resources>
diff --git a/packages/SystemUI/res/values-uz/strings.xml b/packages/SystemUI/res/values-uz/strings.xml
index 0cead71..1128b297 100644
--- a/packages/SystemUI/res/values-uz/strings.xml
+++ b/packages/SystemUI/res/values-uz/strings.xml
@@ -20,19 +20,17 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_label" msgid="4811759950673118541">"Tizim interfeysi"</string>
- <!-- no translation found for battery_low_title (5319680173344341779) -->
- <skip />
- <!-- no translation found for battery_low_description (3282977755476423966) -->
- <skip />
- <!-- no translation found for battery_low_intro (5148725009653088790) -->
- <skip />
+ <string name="battery_low_title" msgid="5319680173344341779">"Quvvat tejash funksiyasi yoqilsinmi?"</string>
+ <string name="battery_low_description" msgid="3282977755476423966">"<xliff:g id="PERCENTAGE">%s</xliff:g> batareya quvvati qoldi. Quvvat tejash funksiyasi Tungi mavzuni yoqadi va fondagi faollikni cheklaydi. Buning natijasida bildirishnomalar kechikishi mumkin."</string>
+ <string name="battery_low_intro" msgid="5148725009653088790">"Quvvat tejash funksiyasi Tungi mavzuni yoqadi va fondagi faollikni cheklaydi. Buning natijasida bildirishnomalar kechikishi mumkin."</string>
<string name="battery_low_percent_format" msgid="4276661262843170964">"<xliff:g id="PERCENTAGE">%s</xliff:g> qoldi"</string>
<string name="invalid_charger_title" msgid="938685362320735167">"USB orqali quvvatlash imkonsiz"</string>
<string name="invalid_charger_text" msgid="2339310107232691577">"Qurilmangiz bilan kelgan quvvatlash moslamasidan foydalaning"</string>
<string name="battery_saver_confirmation_title" msgid="1234998463717398453">"Quvvat tejash yoqilsinmi?"</string>
<string name="battery_saver_confirmation_title_generic" msgid="2299231884234959849">"Quvvat tejash funksiyasi haqida"</string>
<string name="battery_saver_confirmation_ok" msgid="5042136476802816494">"Yoqish"</string>
- <string name="battery_saver_start_action" msgid="4553256017945469937">"Quvvat tejash funksiyasini yoqing"</string>
+ <string name="battery_saver_start_action" msgid="8353766979886287140">"Yoqish"</string>
+ <string name="battery_saver_dismiss_action" msgid="7199342621040014738">"Kerak emas"</string>
<string name="status_bar_settings_auto_rotation" msgid="8329080442278431708">"Ekranning avtomatik burilishi"</string>
<string name="usb_device_permission_prompt" msgid="4414719028369181772">"<xliff:g id="APPLICATION">%1$s</xliff:g> ilovasiga <xliff:g id="USB_DEVICE">%2$s</xliff:g> qurilmasidan foydalanishga ruxsat berilsinmi?"</string>
<string name="usb_device_permission_prompt_warn" msgid="2309129784984063656">"<xliff:g id="APPLICATION">%1$s</xliff:g> ilovasiga <xliff:g id="USB_DEVICE">%2$s</xliff:g> qurilmasidan foydalanish uchun ruxsat berilsinmi?\nBu ilovaga yozib olish ruxsati berilmagan, lekin shu USB orqali ovozlarni yozib olishi mumkin."</string>
@@ -133,8 +131,7 @@
<string name="biometric_dialog_face_icon_description_authenticated" msgid="2242167416140740920">"Yuzingiz aniqlandi"</string>
<string name="biometric_dialog_face_icon_description_confirmed" msgid="7918067993953940778">"Tasdiqlangan"</string>
<string name="biometric_dialog_tap_confirm" msgid="9166350738859143358">"Tasdiqlash uchun tegining"</string>
- <!-- no translation found for biometric_dialog_tap_confirm_with_face (1597899891472340950) -->
- <skip />
+ <string name="biometric_dialog_tap_confirm_with_face" msgid="1597899891472340950">"Yuz bilan ochildi. Davom etish uchun bosing."</string>
<string name="biometric_dialog_authenticated" msgid="7337147327545272484">"Tasdiqlandi"</string>
<string name="biometric_dialog_use_pin" msgid="8385294115283000709">"PIN kod kiritish"</string>
<string name="biometric_dialog_use_pattern" msgid="2315593393167211194">"Grafik kalitdan foydalanish"</string>
@@ -462,8 +459,8 @@
<string name="wallet_secondary_label_device_locked" msgid="5175862019125370506">"Foydalanish uchun qulfdan chiqarish"</string>
<string name="wallet_error_generic" msgid="257704570182963611">"Bildirgilarni yuklashda xatolik yuz berdi, keyinroq qaytadan urining"</string>
<string name="wallet_lockscreen_settings_label" msgid="3539105300870383570">"Qulflangan ekran sozlamalari"</string>
- <string name="qr_code_scanner_title" msgid="5660820608548306581">"QR kod"</string>
- <string name="qr_code_scanner_description" msgid="7937603775306661863">"Skanerlash uchun bosing"</string>
+ <!-- no translation found for qr_code_scanner_title (5290201053875420785) -->
+ <skip />
<string name="status_bar_work" msgid="5238641949837091056">"Ish profili"</string>
<string name="status_bar_airplane" msgid="4848702508684541009">"Parvoz rejimi"</string>
<string name="zen_alarm_warning" msgid="7844303238486849503">"Keyingi signal (<xliff:g id="WHEN">%1$s</xliff:g>) chalinmaydi"</string>
@@ -827,6 +824,7 @@
<string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"Yangi qurilmani ulash"</string>
<string name="media_output_dialog_launch_app_text" msgid="1527413319632586259">"Bu seansni translatsiya qilish uchun ilovani oching."</string>
<string name="media_output_dialog_unknown_launch_app_name" msgid="1084899329829371336">"Notanish ilova"</string>
+ <string name="media_output_dialog_button_stop_casting" msgid="6581379537930199189">"Toʻxtatish"</string>
<string name="build_number_clip_data_label" msgid="3623176728412560914">"Nashr raqami"</string>
<string name="build_number_copy_toast" msgid="877720921605503046">"Nashr raqami vaqtinchalik xotiraga nusxalandi."</string>
<string name="basic_status" msgid="2315371112182658176">"Suhbatni ochish"</string>
@@ -916,7 +914,6 @@
<string name="dream_overlay_status_bar_wifi_off" msgid="4497069245055003582">"Wi‑Fi ishlamayapti"</string>
<string name="dream_overlay_status_bar_priority_mode" msgid="5428462123314728739">"Imtiyozli rejim"</string>
<string name="dream_overlay_status_bar_alarm_set" msgid="566707328356590886">"Signal oʻrnatildi"</string>
- <string name="dream_overlay_status_bar_assistant_guest_mode_enabled" msgid="3715897096012469615">"Assistentli mehmon rejimi yoqildi"</string>
<string name="dream_overlay_status_bar_camera_mic_off" msgid="3199425257833773569">"Kamera va mikrofon yoqilmagan"</string>
<string name="dream_overlay_status_bar_notification_indicator" msgid="8091389255691081711">"{count,plural, =1{# ta bildirishnoma}other{# ta bildirishnoma}}"</string>
</resources>
diff --git a/packages/SystemUI/res/values-vi/strings.xml b/packages/SystemUI/res/values-vi/strings.xml
index a5609eb8..068127b 100644
--- a/packages/SystemUI/res/values-vi/strings.xml
+++ b/packages/SystemUI/res/values-vi/strings.xml
@@ -20,19 +20,17 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_label" msgid="4811759950673118541">"Giao diện người dùng hệ thống"</string>
- <!-- no translation found for battery_low_title (5319680173344341779) -->
- <skip />
- <!-- no translation found for battery_low_description (3282977755476423966) -->
- <skip />
- <!-- no translation found for battery_low_intro (5148725009653088790) -->
- <skip />
+ <string name="battery_low_title" msgid="5319680173344341779">"Bật Trình tiết kiệm pin?"</string>
+ <string name="battery_low_description" msgid="3282977755476423966">"Bạn còn <xliff:g id="PERCENTAGE">%s</xliff:g> pin. Trình tiết kiệm pin sẽ bật Giao diện tối, giới hạn hoạt động trong nền và trì hoãn thông báo."</string>
+ <string name="battery_low_intro" msgid="5148725009653088790">"Trình tiết kiệm pin sẽ bật Giao diện tối, giới hạn hoạt động trong nền và trì hoãn thông báo."</string>
<string name="battery_low_percent_format" msgid="4276661262843170964">"Còn lại <xliff:g id="PERCENTAGE">%s</xliff:g>"</string>
<string name="invalid_charger_title" msgid="938685362320735167">"Không thể sạc qua USB"</string>
<string name="invalid_charger_text" msgid="2339310107232691577">"Sử dụng bộ sạc đi kèm với thiết bị"</string>
<string name="battery_saver_confirmation_title" msgid="1234998463717398453">"Bật trình tiết kiệm pin?"</string>
<string name="battery_saver_confirmation_title_generic" msgid="2299231884234959849">"Giới thiệu về Trình tiết kiệm pin"</string>
<string name="battery_saver_confirmation_ok" msgid="5042136476802816494">"Bật"</string>
- <string name="battery_saver_start_action" msgid="4553256017945469937">"Bật trình tiết kiệm pin"</string>
+ <string name="battery_saver_start_action" msgid="8353766979886287140">"Bật"</string>
+ <string name="battery_saver_dismiss_action" msgid="7199342621040014738">"Không, cảm ơn"</string>
<string name="status_bar_settings_auto_rotation" msgid="8329080442278431708">"Tự động xoay màn hình"</string>
<string name="usb_device_permission_prompt" msgid="4414719028369181772">"Cho phép <xliff:g id="APPLICATION">%1$s</xliff:g> truy cập <xliff:g id="USB_DEVICE">%2$s</xliff:g>?"</string>
<string name="usb_device_permission_prompt_warn" msgid="2309129784984063656">"Cho phép <xliff:g id="APPLICATION">%1$s</xliff:g> truy cập vào <xliff:g id="USB_DEVICE">%2$s</xliff:g>?\nỨng dụng này chưa được cấp quyền ghi âm nhưng vẫn có thể ghi âm thông qua thiết bị USB này."</string>
@@ -133,8 +131,7 @@
<string name="biometric_dialog_face_icon_description_authenticated" msgid="2242167416140740920">"Đã xác thực khuôn mặt"</string>
<string name="biometric_dialog_face_icon_description_confirmed" msgid="7918067993953940778">"Ðã xác nhận"</string>
<string name="biometric_dialog_tap_confirm" msgid="9166350738859143358">"Nhấn vào Xác nhận để hoàn tất"</string>
- <!-- no translation found for biometric_dialog_tap_confirm_with_face (1597899891472340950) -->
- <skip />
+ <string name="biometric_dialog_tap_confirm_with_face" msgid="1597899891472340950">"Đã mở khoá bằng khuôn mặt bạn. Hãy nhấn để tiếp tục."</string>
<string name="biometric_dialog_authenticated" msgid="7337147327545272484">"Đã xác thực"</string>
<string name="biometric_dialog_use_pin" msgid="8385294115283000709">"Dùng mã PIN"</string>
<string name="biometric_dialog_use_pattern" msgid="2315593393167211194">"Dùng hình mở khóa"</string>
@@ -462,8 +459,8 @@
<string name="wallet_secondary_label_device_locked" msgid="5175862019125370506">"Mở khóa để sử dụng"</string>
<string name="wallet_error_generic" msgid="257704570182963611">"Đã xảy ra sự cố khi tải thẻ của bạn. Vui lòng thử lại sau"</string>
<string name="wallet_lockscreen_settings_label" msgid="3539105300870383570">"Cài đặt màn hình khóa"</string>
- <string name="qr_code_scanner_title" msgid="5660820608548306581">"Mã QR"</string>
- <string name="qr_code_scanner_description" msgid="7937603775306661863">"Nhấn để quét"</string>
+ <!-- no translation found for qr_code_scanner_title (5290201053875420785) -->
+ <skip />
<string name="status_bar_work" msgid="5238641949837091056">"Hồ sơ công việc"</string>
<string name="status_bar_airplane" msgid="4848702508684541009">"Chế độ máy bay"</string>
<string name="zen_alarm_warning" msgid="7844303238486849503">"Bạn sẽ không nghe thấy báo thức tiếp theo lúc <xliff:g id="WHEN">%1$s</xliff:g> của mình"</string>
@@ -827,6 +824,7 @@
<string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"Ghép nối thiết bị mới"</string>
<string name="media_output_dialog_launch_app_text" msgid="1527413319632586259">"Vui lòng mở ứng dụng để truyền phiên này."</string>
<string name="media_output_dialog_unknown_launch_app_name" msgid="1084899329829371336">"Ứng dụng không xác định"</string>
+ <string name="media_output_dialog_button_stop_casting" msgid="6581379537930199189">"Dừng truyền"</string>
<string name="build_number_clip_data_label" msgid="3623176728412560914">"Số bản dựng"</string>
<string name="build_number_copy_toast" msgid="877720921605503046">"Đã sao chép số bản dựng vào bảng nhớ tạm."</string>
<string name="basic_status" msgid="2315371112182658176">"Mở cuộc trò chuyện"</string>
@@ -916,8 +914,6 @@
<string name="dream_overlay_status_bar_wifi_off" msgid="4497069245055003582">"Không có Wi‑Fi"</string>
<string name="dream_overlay_status_bar_priority_mode" msgid="5428462123314728739">"Chế độ ưu tiên"</string>
<string name="dream_overlay_status_bar_alarm_set" msgid="566707328356590886">"Đã đặt chuông báo"</string>
- <string name="dream_overlay_status_bar_assistant_guest_mode_enabled" msgid="3715897096012469615">"Đã bật chế độ khách cho Trợ lý"</string>
<string name="dream_overlay_status_bar_camera_mic_off" msgid="3199425257833773569">"Máy ảnh và micrô đang tắt"</string>
- <!-- no translation found for dream_overlay_status_bar_notification_indicator (8091389255691081711) -->
- <skip />
+ <string name="dream_overlay_status_bar_notification_indicator" msgid="8091389255691081711">"{count,plural, =1{# thông báo}other{# thông báo}}"</string>
</resources>
diff --git a/packages/SystemUI/res/values-zh-rCN/strings.xml b/packages/SystemUI/res/values-zh-rCN/strings.xml
index 0610b59..b5671e6 100644
--- a/packages/SystemUI/res/values-zh-rCN/strings.xml
+++ b/packages/SystemUI/res/values-zh-rCN/strings.xml
@@ -20,19 +20,17 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_label" msgid="4811759950673118541">"系统界面"</string>
- <!-- no translation found for battery_low_title (5319680173344341779) -->
- <skip />
- <!-- no translation found for battery_low_description (3282977755476423966) -->
- <skip />
- <!-- no translation found for battery_low_intro (5148725009653088790) -->
- <skip />
+ <string name="battery_low_title" msgid="5319680173344341779">"要开启省电模式吗?"</string>
+ <string name="battery_low_description" msgid="3282977755476423966">"您的电池还剩 <xliff:g id="PERCENTAGE">%s</xliff:g> 的电量。省电模式会开启深色主题,限制后台活动并将通知延迟。"</string>
+ <string name="battery_low_intro" msgid="5148725009653088790">"省电模式会开启深色主题,限制后台活动并将通知延迟。"</string>
<string name="battery_low_percent_format" msgid="4276661262843170964">"剩余<xliff:g id="PERCENTAGE">%s</xliff:g>"</string>
<string name="invalid_charger_title" msgid="938685362320735167">"无法通过 USB 充电"</string>
<string name="invalid_charger_text" msgid="2339310107232691577">"使用设备随附的充电器"</string>
<string name="battery_saver_confirmation_title" msgid="1234998463717398453">"要开启省电模式吗?"</string>
<string name="battery_saver_confirmation_title_generic" msgid="2299231884234959849">"关于省电模式"</string>
<string name="battery_saver_confirmation_ok" msgid="5042136476802816494">"开启"</string>
- <string name="battery_saver_start_action" msgid="4553256017945469937">"开启省电模式"</string>
+ <string name="battery_saver_start_action" msgid="8353766979886287140">"开启"</string>
+ <string name="battery_saver_dismiss_action" msgid="7199342621040014738">"不用了"</string>
<string name="status_bar_settings_auto_rotation" msgid="8329080442278431708">"自动旋转屏幕"</string>
<string name="usb_device_permission_prompt" msgid="4414719028369181772">"要允许<xliff:g id="APPLICATION">%1$s</xliff:g>访问<xliff:g id="USB_DEVICE">%2$s</xliff:g>吗?"</string>
<string name="usb_device_permission_prompt_warn" msgid="2309129784984063656">"是否允许<xliff:g id="APPLICATION">%1$s</xliff:g>访问<xliff:g id="USB_DEVICE">%2$s</xliff:g>?\n此应用未获得录音权限,但能通过此 USB 设备录制音频。"</string>
@@ -133,8 +131,7 @@
<string name="biometric_dialog_face_icon_description_authenticated" msgid="2242167416140740920">"面孔身份验证成功"</string>
<string name="biometric_dialog_face_icon_description_confirmed" msgid="7918067993953940778">"已确认"</string>
<string name="biometric_dialog_tap_confirm" msgid="9166350738859143358">"点按“确认”即可完成"</string>
- <!-- no translation found for biometric_dialog_tap_confirm_with_face (1597899891472340950) -->
- <skip />
+ <string name="biometric_dialog_tap_confirm_with_face" msgid="1597899891472340950">"已通过面孔识别解锁。点按即可继续。"</string>
<string name="biometric_dialog_authenticated" msgid="7337147327545272484">"已经过身份验证"</string>
<string name="biometric_dialog_use_pin" msgid="8385294115283000709">"使用 PIN 码"</string>
<string name="biometric_dialog_use_pattern" msgid="2315593393167211194">"使用图案"</string>
@@ -462,8 +459,8 @@
<string name="wallet_secondary_label_device_locked" msgid="5175862019125370506">"解锁设备即可使用"</string>
<string name="wallet_error_generic" msgid="257704570182963611">"获取您的卡片时出现问题,请稍后重试"</string>
<string name="wallet_lockscreen_settings_label" msgid="3539105300870383570">"锁定屏幕设置"</string>
- <string name="qr_code_scanner_title" msgid="5660820608548306581">"二维码"</string>
- <string name="qr_code_scanner_description" msgid="7937603775306661863">"点按即可扫描"</string>
+ <!-- no translation found for qr_code_scanner_title (5290201053875420785) -->
+ <skip />
<string name="status_bar_work" msgid="5238641949837091056">"工作资料"</string>
<string name="status_bar_airplane" msgid="4848702508684541009">"飞行模式"</string>
<string name="zen_alarm_warning" msgid="7844303238486849503">"您在<xliff:g id="WHEN">%1$s</xliff:g>将不会听到下次闹钟响铃"</string>
@@ -827,6 +824,7 @@
<string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"与新设备配对"</string>
<string name="media_output_dialog_launch_app_text" msgid="1527413319632586259">"如需投射此会话,请打开相关应用。"</string>
<string name="media_output_dialog_unknown_launch_app_name" msgid="1084899329829371336">"未知应用"</string>
+ <string name="media_output_dialog_button_stop_casting" msgid="6581379537930199189">"停止投射"</string>
<string name="build_number_clip_data_label" msgid="3623176728412560914">"版本号"</string>
<string name="build_number_copy_toast" msgid="877720921605503046">"已将版本号复制到剪贴板。"</string>
<string name="basic_status" msgid="2315371112182658176">"开放式对话"</string>
@@ -916,8 +914,6 @@
<string name="dream_overlay_status_bar_wifi_off" msgid="4497069245055003582">"WLAN 已关闭"</string>
<string name="dream_overlay_status_bar_priority_mode" msgid="5428462123314728739">"优先模式"</string>
<string name="dream_overlay_status_bar_alarm_set" msgid="566707328356590886">"闹钟已设置"</string>
- <string name="dream_overlay_status_bar_assistant_guest_mode_enabled" msgid="3715897096012469615">"Google 助理访客模式已启用"</string>
<string name="dream_overlay_status_bar_camera_mic_off" msgid="3199425257833773569">"摄像头和麦克风已关闭"</string>
- <!-- no translation found for dream_overlay_status_bar_notification_indicator (8091389255691081711) -->
- <skip />
+ <string name="dream_overlay_status_bar_notification_indicator" msgid="8091389255691081711">"{count,plural, =1{# 条通知}other{# 条通知}}"</string>
</resources>
diff --git a/packages/SystemUI/res/values-zh-rHK/strings.xml b/packages/SystemUI/res/values-zh-rHK/strings.xml
index 8600859..718d5e1 100644
--- a/packages/SystemUI/res/values-zh-rHK/strings.xml
+++ b/packages/SystemUI/res/values-zh-rHK/strings.xml
@@ -20,19 +20,17 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_label" msgid="4811759950673118541">"系統使用者介面"</string>
- <!-- no translation found for battery_low_title (5319680173344341779) -->
- <skip />
- <!-- no translation found for battery_low_description (3282977755476423966) -->
- <skip />
- <!-- no translation found for battery_low_intro (5148725009653088790) -->
- <skip />
+ <string name="battery_low_title" msgid="5319680173344341779">"要開啟「省電模式」嗎?"</string>
+ <string name="battery_low_description" msgid="3282977755476423966">"剩餘 <xliff:g id="PERCENTAGE">%s</xliff:g> 電量。「省電模式」會開啟深色主題背景、限制背景活動,並延遲顯示通知。"</string>
+ <string name="battery_low_intro" msgid="5148725009653088790">"「省電模式」會開啟深色主題背景、限制背景活動,並延遲顯示通知。"</string>
<string name="battery_low_percent_format" msgid="4276661262843170964">"剩餘 <xliff:g id="PERCENTAGE">%s</xliff:g>"</string>
<string name="invalid_charger_title" msgid="938685362320735167">"無法透過 USB 充電"</string>
<string name="invalid_charger_text" msgid="2339310107232691577">"使用裝置隨附的充電器"</string>
<string name="battery_saver_confirmation_title" msgid="1234998463717398453">"要開啟省電模式嗎?"</string>
<string name="battery_saver_confirmation_title_generic" msgid="2299231884234959849">"關於「省電模式」"</string>
<string name="battery_saver_confirmation_ok" msgid="5042136476802816494">"開啟"</string>
- <string name="battery_saver_start_action" msgid="4553256017945469937">"開啟省電模式"</string>
+ <string name="battery_saver_start_action" msgid="8353766979886287140">"開啟"</string>
+ <string name="battery_saver_dismiss_action" msgid="7199342621040014738">"不用了,謝謝"</string>
<string name="status_bar_settings_auto_rotation" msgid="8329080442278431708">"自動旋轉螢幕"</string>
<string name="usb_device_permission_prompt" msgid="4414719028369181772">"要允許「<xliff:g id="APPLICATION">%1$s</xliff:g>」存取「<xliff:g id="USB_DEVICE">%2$s</xliff:g>」嗎?"</string>
<string name="usb_device_permission_prompt_warn" msgid="2309129784984063656">"要允許「<xliff:g id="APPLICATION">%1$s</xliff:g>」存取「<xliff:g id="USB_DEVICE">%2$s</xliff:g>」嗎?\n此應用程式尚未獲授予錄音權限,但可透過此 USB 裝置記錄音訊。"</string>
@@ -133,8 +131,7 @@
<string name="biometric_dialog_face_icon_description_authenticated" msgid="2242167416140740920">"臉孔已經驗證"</string>
<string name="biometric_dialog_face_icon_description_confirmed" msgid="7918067993953940778">"已確認"</string>
<string name="biometric_dialog_tap_confirm" msgid="9166350738859143358">"輕按 [確定] 以完成"</string>
- <!-- no translation found for biometric_dialog_tap_confirm_with_face (1597899891472340950) -->
- <skip />
+ <string name="biometric_dialog_tap_confirm_with_face" msgid="1597899891472340950">"您已使用面孔解鎖。按下即可繼續操作。"</string>
<string name="biometric_dialog_authenticated" msgid="7337147327545272484">"驗證咗"</string>
<string name="biometric_dialog_use_pin" msgid="8385294115283000709">"使用 PIN"</string>
<string name="biometric_dialog_use_pattern" msgid="2315593393167211194">"使用圖案"</string>
@@ -462,8 +459,8 @@
<string name="wallet_secondary_label_device_locked" msgid="5175862019125370506">"解鎖即可使用"</string>
<string name="wallet_error_generic" msgid="257704570182963611">"擷取資訊卡時發生問題,請稍後再試。"</string>
<string name="wallet_lockscreen_settings_label" msgid="3539105300870383570">"上鎖畫面設定"</string>
- <string name="qr_code_scanner_title" msgid="5660820608548306581">"QR 碼"</string>
- <string name="qr_code_scanner_description" msgid="7937603775306661863">"輕按即可掃瞄"</string>
+ <!-- no translation found for qr_code_scanner_title (5290201053875420785) -->
+ <skip />
<string name="status_bar_work" msgid="5238641949837091056">"工作設定檔"</string>
<string name="status_bar_airplane" msgid="4848702508684541009">"飛行模式"</string>
<string name="zen_alarm_warning" msgid="7844303238486849503">"您不會<xliff:g id="WHEN">%1$s</xliff:g>聽到鬧鐘"</string>
@@ -827,6 +824,7 @@
<string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"配對新裝置"</string>
<string name="media_output_dialog_launch_app_text" msgid="1527413319632586259">"如要投放此工作階段,請開啟應用程式。"</string>
<string name="media_output_dialog_unknown_launch_app_name" msgid="1084899329829371336">"不明應用程式"</string>
+ <string name="media_output_dialog_button_stop_casting" msgid="6581379537930199189">"停止投放"</string>
<string name="build_number_clip_data_label" msgid="3623176728412560914">"版本號碼"</string>
<string name="build_number_copy_toast" msgid="877720921605503046">"版本號碼已複製到剪貼簿。"</string>
<string name="basic_status" msgid="2315371112182658176">"開啟對話"</string>
@@ -916,8 +914,6 @@
<string name="dream_overlay_status_bar_wifi_off" msgid="4497069245055003582">"Wi‑Fi 已關閉"</string>
<string name="dream_overlay_status_bar_priority_mode" msgid="5428462123314728739">"優先模式"</string>
<string name="dream_overlay_status_bar_alarm_set" msgid="566707328356590886">"已設定鬧鐘"</string>
- <string name="dream_overlay_status_bar_assistant_guest_mode_enabled" msgid="3715897096012469615">"已啟用「Google 助理」訪客模式"</string>
<string name="dream_overlay_status_bar_camera_mic_off" msgid="3199425257833773569">"相機和麥克風已關閉"</string>
- <!-- no translation found for dream_overlay_status_bar_notification_indicator (8091389255691081711) -->
- <skip />
+ <string name="dream_overlay_status_bar_notification_indicator" msgid="8091389255691081711">"{count,plural, =1{# 則通知}other{# 則通知}}"</string>
</resources>
diff --git a/packages/SystemUI/res/values-zh-rTW/strings.xml b/packages/SystemUI/res/values-zh-rTW/strings.xml
index 0206a9e..dcb74b3 100644
--- a/packages/SystemUI/res/values-zh-rTW/strings.xml
+++ b/packages/SystemUI/res/values-zh-rTW/strings.xml
@@ -20,19 +20,17 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_label" msgid="4811759950673118541">"系統 UI"</string>
- <!-- no translation found for battery_low_title (5319680173344341779) -->
- <skip />
- <!-- no translation found for battery_low_description (3282977755476423966) -->
- <skip />
- <!-- no translation found for battery_low_intro (5148725009653088790) -->
- <skip />
+ <string name="battery_low_title" msgid="5319680173344341779">"要開啟省電模式嗎?"</string>
+ <string name="battery_low_description" msgid="3282977755476423966">"電池電量還剩 <xliff:g id="PERCENTAGE">%s</xliff:g>。省電模式會開啟深色主題、限制背景活動,並延遲顯示通知。"</string>
+ <string name="battery_low_intro" msgid="5148725009653088790">"省電模式會開啟深色主題、限制背景活動,並延遲顯示通知。"</string>
<string name="battery_low_percent_format" msgid="4276661262843170964">"僅剩 <xliff:g id="PERCENTAGE">%s</xliff:g>"</string>
<string name="invalid_charger_title" msgid="938685362320735167">"無法透過 USB 充電"</string>
<string name="invalid_charger_text" msgid="2339310107232691577">"使用裝置隨附的充電器"</string>
<string name="battery_saver_confirmation_title" msgid="1234998463717398453">"要開啟省電模式嗎?"</string>
<string name="battery_saver_confirmation_title_generic" msgid="2299231884234959849">"關於省電模式"</string>
<string name="battery_saver_confirmation_ok" msgid="5042136476802816494">"開啟"</string>
- <string name="battery_saver_start_action" msgid="4553256017945469937">"開啟省電模式"</string>
+ <string name="battery_saver_start_action" msgid="8353766979886287140">"開啟"</string>
+ <string name="battery_saver_dismiss_action" msgid="7199342621040014738">"不用了,謝謝"</string>
<string name="status_bar_settings_auto_rotation" msgid="8329080442278431708">"自動旋轉螢幕"</string>
<string name="usb_device_permission_prompt" msgid="4414719028369181772">"要允許「<xliff:g id="APPLICATION">%1$s</xliff:g>」存取「<xliff:g id="USB_DEVICE">%2$s</xliff:g>」嗎?"</string>
<string name="usb_device_permission_prompt_warn" msgid="2309129784984063656">"要允許「<xliff:g id="APPLICATION">%1$s</xliff:g>」存取「<xliff:g id="USB_DEVICE">%2$s</xliff:g>」嗎?\n這個應用程式未取得錄製權限,但可以透過這部 USB 裝置錄製音訊。"</string>
@@ -133,8 +131,7 @@
<string name="biometric_dialog_face_icon_description_authenticated" msgid="2242167416140740920">"臉孔驗證成功"</string>
<string name="biometric_dialog_face_icon_description_confirmed" msgid="7918067993953940778">"確認完畢"</string>
<string name="biometric_dialog_tap_confirm" msgid="9166350738859143358">"輕觸 [確認] 完成驗證設定"</string>
- <!-- no translation found for biometric_dialog_tap_confirm_with_face (1597899891472340950) -->
- <skip />
+ <string name="biometric_dialog_tap_confirm_with_face" msgid="1597899891472340950">"你已用自己的臉解鎖裝置,按下即可繼續操作。"</string>
<string name="biometric_dialog_authenticated" msgid="7337147327545272484">"已通過驗證"</string>
<string name="biometric_dialog_use_pin" msgid="8385294115283000709">"使用 PIN 碼"</string>
<string name="biometric_dialog_use_pattern" msgid="2315593393167211194">"使用解鎖圖案"</string>
@@ -462,8 +459,8 @@
<string name="wallet_secondary_label_device_locked" msgid="5175862019125370506">"解鎖即可使用"</string>
<string name="wallet_error_generic" msgid="257704570182963611">"擷取卡片時發生問題,請稍後再試"</string>
<string name="wallet_lockscreen_settings_label" msgid="3539105300870383570">"螢幕鎖定設定"</string>
- <string name="qr_code_scanner_title" msgid="5660820608548306581">"QR 圖碼"</string>
- <string name="qr_code_scanner_description" msgid="7937603775306661863">"輕觸即可掃描"</string>
+ <!-- no translation found for qr_code_scanner_title (5290201053875420785) -->
+ <skip />
<string name="status_bar_work" msgid="5238641949837091056">"工作資料夾"</string>
<string name="status_bar_airplane" msgid="4848702508684541009">"飛航模式"</string>
<string name="zen_alarm_warning" msgid="7844303238486849503">"你不會聽到下一個<xliff:g id="WHEN">%1$s</xliff:g> 的鬧鐘"</string>
@@ -827,6 +824,7 @@
<string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"配對新裝置"</string>
<string name="media_output_dialog_launch_app_text" msgid="1527413319632586259">"如要投放這個工作階段,請開啟應用程式。"</string>
<string name="media_output_dialog_unknown_launch_app_name" msgid="1084899329829371336">"不明的應用程式"</string>
+ <string name="media_output_dialog_button_stop_casting" msgid="6581379537930199189">"停止投放"</string>
<string name="build_number_clip_data_label" msgid="3623176728412560914">"版本號碼"</string>
<string name="build_number_copy_toast" msgid="877720921605503046">"已將版本號碼複製到剪貼簿。"</string>
<string name="basic_status" msgid="2315371112182658176">"開放式對話"</string>
@@ -916,8 +914,6 @@
<string name="dream_overlay_status_bar_wifi_off" msgid="4497069245055003582">"Wi‑Fi 已關閉"</string>
<string name="dream_overlay_status_bar_priority_mode" msgid="5428462123314728739">"優先模式"</string>
<string name="dream_overlay_status_bar_alarm_set" msgid="566707328356590886">"鬧鐘設定成功"</string>
- <string name="dream_overlay_status_bar_assistant_guest_mode_enabled" msgid="3715897096012469615">"已啟用 Google 助理訪客模式"</string>
<string name="dream_overlay_status_bar_camera_mic_off" msgid="3199425257833773569">"已關閉相機和麥克風"</string>
- <!-- no translation found for dream_overlay_status_bar_notification_indicator (8091389255691081711) -->
- <skip />
+ <string name="dream_overlay_status_bar_notification_indicator" msgid="8091389255691081711">"{count,plural, =1{# 則通知}other{# 則通知}}"</string>
</resources>
diff --git a/packages/SystemUI/res/values-zu/strings.xml b/packages/SystemUI/res/values-zu/strings.xml
index 98e7fc4..f26ef0e 100644
--- a/packages/SystemUI/res/values-zu/strings.xml
+++ b/packages/SystemUI/res/values-zu/strings.xml
@@ -20,19 +20,17 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_label" msgid="4811759950673118541">"Uhlelo lwe-UI"</string>
- <!-- no translation found for battery_low_title (5319680173344341779) -->
- <skip />
- <!-- no translation found for battery_low_description (3282977755476423966) -->
- <skip />
- <!-- no translation found for battery_low_intro (5148725009653088790) -->
- <skip />
+ <string name="battery_low_title" msgid="5319680173344341779">"Vula Isilondolozi Sebhethri?"</string>
+ <string name="battery_low_description" msgid="3282977755476423966">"Usele ngo-<xliff:g id="PERCENTAGE">%s</xliff:g> kwibhethri. Isilondolozi Sebhethri sivula itimu Emnyama, sikhawulela umsebenzi wangemuva, futhi sibambezele izaziso."</string>
+ <string name="battery_low_intro" msgid="5148725009653088790">"Isilondolozi Sebhethri sivula itimu Emnyama, sikhawulela umsebenzi wangemuva, futhi sibambezele izaziso."</string>
<string name="battery_low_percent_format" msgid="4276661262843170964">"<xliff:g id="PERCENTAGE">%s</xliff:g> okusele"</string>
<string name="invalid_charger_title" msgid="938685362320735167">"Ayikwazi ukushaja nge-USB"</string>
<string name="invalid_charger_text" msgid="2339310107232691577">"Sebenzisa ishaja eze nedivayisi yakho"</string>
<string name="battery_saver_confirmation_title" msgid="1234998463717398453">"Vula isilondolozi sebhethri?"</string>
<string name="battery_saver_confirmation_title_generic" msgid="2299231884234959849">"Mayelana nesilondolozi sebhethri"</string>
<string name="battery_saver_confirmation_ok" msgid="5042136476802816494">"Vula"</string>
- <string name="battery_saver_start_action" msgid="4553256017945469937">"Vula isilondolozi sebhethri"</string>
+ <string name="battery_saver_start_action" msgid="8353766979886287140">"Vula"</string>
+ <string name="battery_saver_dismiss_action" msgid="7199342621040014738">"Cha ngiyabonga"</string>
<string name="status_bar_settings_auto_rotation" msgid="8329080442278431708">"Ukuzulazula kweskrini okuzenzakalelayo"</string>
<string name="usb_device_permission_prompt" msgid="4414719028369181772">"Vumela i-<xliff:g id="APPLICATION">%1$s</xliff:g> ukufinyelela i-<xliff:g id="USB_DEVICE">%2$s</xliff:g>?"</string>
<string name="usb_device_permission_prompt_warn" msgid="2309129784984063656">"Vumela i-<xliff:g id="APPLICATION">%1$s</xliff:g> ukuthi ifinyelele ku-<xliff:g id="USB_DEVICE">%2$s</xliff:g>?\nLolu hlelo lokusebenza alunikeziwe imvume yokurekhoda kodwa lingathatha umsindo ngale divayisi ye-USB."</string>
@@ -133,8 +131,7 @@
<string name="biometric_dialog_face_icon_description_authenticated" msgid="2242167416140740920">"Ubuso bufakazelwe ubuqiniso"</string>
<string name="biometric_dialog_face_icon_description_confirmed" msgid="7918067993953940778">"Kuqinisekisiwe"</string>
<string name="biometric_dialog_tap_confirm" msgid="9166350738859143358">"Thepha okuthi Qinisekisa ukuze uqedele"</string>
- <!-- no translation found for biometric_dialog_tap_confirm_with_face (1597899891472340950) -->
- <skip />
+ <string name="biometric_dialog_tap_confirm_with_face" msgid="1597899891472340950">"Ivulwe ngobuso bakho. Cindezela ukuze uqhubeke."</string>
<string name="biometric_dialog_authenticated" msgid="7337147327545272484">"Kugunyaziwe"</string>
<string name="biometric_dialog_use_pin" msgid="8385294115283000709">"Sebenzisa iphinikhodi"</string>
<string name="biometric_dialog_use_pattern" msgid="2315593393167211194">"Sebenzisa iphethini"</string>
@@ -462,8 +459,8 @@
<string name="wallet_secondary_label_device_locked" msgid="5175862019125370506">"Vula ukuze usebenzise"</string>
<string name="wallet_error_generic" msgid="257704570182963611">"Kube khona inkinga yokuthola amakhadi akho, sicela uzame futhi ngemuva kwesikhathi"</string>
<string name="wallet_lockscreen_settings_label" msgid="3539105300870383570">"Amasethingi okukhiya isikrini"</string>
- <string name="qr_code_scanner_title" msgid="5660820608548306581">"Ikhodi ye-QR"</string>
- <string name="qr_code_scanner_description" msgid="7937603775306661863">"Thepha ukuze uskene"</string>
+ <!-- no translation found for qr_code_scanner_title (5290201053875420785) -->
+ <skip />
<string name="status_bar_work" msgid="5238641949837091056">"Iphrofayela yomsebenzi"</string>
<string name="status_bar_airplane" msgid="4848702508684541009">"Imodi yendiza"</string>
<string name="zen_alarm_warning" msgid="7844303238486849503">"Ngeke uzwe i-alamu yakho elandelayo ngo-<xliff:g id="WHEN">%1$s</xliff:g>"</string>
@@ -827,6 +824,7 @@
<string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"Bhangqa idivayisi entsha"</string>
<string name="media_output_dialog_launch_app_text" msgid="1527413319632586259">"Ukuze usakaze le seshini, sicela uvule i-app."</string>
<string name="media_output_dialog_unknown_launch_app_name" msgid="1084899329829371336">"I-app engaziwa"</string>
+ <string name="media_output_dialog_button_stop_casting" msgid="6581379537930199189">"Misa ukusakaza"</string>
<string name="build_number_clip_data_label" msgid="3623176728412560914">"Yakha inombolo"</string>
<string name="build_number_copy_toast" msgid="877720921605503046">"Yakha inombolo ekopishelwe kubhodi yokunamathisela."</string>
<string name="basic_status" msgid="2315371112182658176">"Vula ingxoxo"</string>
@@ -916,8 +914,6 @@
<string name="dream_overlay_status_bar_wifi_off" msgid="4497069245055003582">"I-Wi-Fi ayitholakali"</string>
<string name="dream_overlay_status_bar_priority_mode" msgid="5428462123314728739">"Imodi ebalulekile"</string>
<string name="dream_overlay_status_bar_alarm_set" msgid="566707328356590886">"I-alamu isethiwe"</string>
- <string name="dream_overlay_status_bar_assistant_guest_mode_enabled" msgid="3715897096012469615">"Imodi yesivakashi somsizi inikwe amandla"</string>
<string name="dream_overlay_status_bar_camera_mic_off" msgid="3199425257833773569">"Ikhamera nemakrofoni kuvaliwe"</string>
- <!-- no translation found for dream_overlay_status_bar_notification_indicator (8091389255691081711) -->
- <skip />
+ <string name="dream_overlay_status_bar_notification_indicator" msgid="8091389255691081711">"{count,plural, =1{Isaziso esingu-#}one{Izaziso ezingu-#}other{Izaziso ezingu-#}}"</string>
</resources>
diff --git a/packages/SystemUI/res/values/colors.xml b/packages/SystemUI/res/values/colors.xml
index 1edaaad..49fc848 100644
--- a/packages/SystemUI/res/values/colors.xml
+++ b/packages/SystemUI/res/values/colors.xml
@@ -176,10 +176,12 @@
<!-- media output dialog-->
<color name="media_dialog_background" android:lstar="98">@color/material_dynamic_neutral90</color>
- <color name="media_dialog_active_item_main_content">@color/material_dynamic_primary10</color>
- <color name="media_dialog_inactive_item_main_content">@color/material_dynamic_primary40</color>
- <color name="media_dialog_item_status">@color/material_dynamic_primary10</color>
+ <color name="media_dialog_item_main_content">@color/material_dynamic_primary20</color>
<color name="media_dialog_item_background">@color/material_dynamic_secondary95</color>
+ <color name="media_dialog_connected_item_background">@color/material_dynamic_primary90</color>
+ <color name="media_dialog_seekbar_progress">@color/material_dynamic_secondary40</color>
+ <color name="media_dialog_button_background">@color/material_dynamic_primary40</color>
+ <color name="media_dialog_solid_button_text">@color/material_dynamic_neutral95</color>
<!-- controls -->
<color name="control_primary_text">#E6FFFFFF</color>
diff --git a/packages/SystemUI/res/values/config.xml b/packages/SystemUI/res/values/config.xml
index a0a8768..9ea3618 100644
--- a/packages/SystemUI/res/values/config.xml
+++ b/packages/SystemUI/res/values/config.xml
@@ -707,4 +707,18 @@
<integer name="complicationFadeInMs">500</integer>
<integer name="complicationRestoreMs">1000</integer>
+
+ <!-- Icons that don't show in a collapsed non-keyguard statusbar -->
+ <string-array name="config_collapsed_statusbar_icon_blocklist" translatable="false">
+ <item>@*android:string/status_bar_volume</item>
+ <item>@*android:string/status_bar_alarm_clock</item>
+ <item>@*android:string/status_bar_call_strength</item>
+ </string-array>
+
+ <!-- Icons that don't show in a collapsed statusbar on keyguard -->
+ <string-array name="config_keyguard_statusbar_icon_blocklist" translatable="false">
+ <item>@*android:string/status_bar_volume</item>
+ <item>@*android:string/status_bar_alarm_clock</item>
+ <item>@*android:string/status_bar_call_strength</item>
+ </string-array>
</resources>
diff --git a/packages/SystemUI/res/values/dimens.xml b/packages/SystemUI/res/values/dimens.xml
index 52ec516..8f4e115 100644
--- a/packages/SystemUI/res/values/dimens.xml
+++ b/packages/SystemUI/res/values/dimens.xml
@@ -941,6 +941,9 @@
<!-- Three privacy items. This value must not be exceeded -->
<dimen name="ongoing_appops_chip_max_width">76dp</dimen>
<dimen name="ongoing_appops_dot_diameter">6dp</dimen>
+ <dimen name="ongoing_appops_chip_min_animation_width">10dp</dimen>
+ <dimen name="ongoing_appops_chip_animation_in_status_bar_translation_x">15dp</dimen>
+ <dimen name="ongoing_appops_chip_animation_out_status_bar_translation_x">7dp</dimen>
<!-- Total minimum padding to enforce to ensure that the dot can always show -->
<dimen name="ongoing_appops_dot_min_padding">20dp</dimen>
@@ -1005,6 +1008,9 @@
<!-- Media tap-to-transfer chip for receiver device -->
<dimen name="media_ttt_chip_size_receiver">100dp</dimen>
<dimen name="media_ttt_icon_size_receiver">95dp</dimen>
+ <!-- Since the generic icon isn't circular, we need to scale it down so it still fits within
+ the circular chip. -->
+ <dimen name="media_ttt_generic_icon_size_receiver">70dp</dimen>
<!-- Window magnification -->
<dimen name="magnification_border_drag_size">35dp</dimen>
@@ -1138,6 +1144,12 @@
the shade (in alpha) -->
<dimen name="lockscreen_shade_scrim_transition_distance">@dimen/lockscreen_shade_full_transition_distance</dimen>
+ <!-- Distance that it takes in order for the notifications scrim fade in to start. -->
+ <dimen name="lockscreen_shade_notifications_scrim_transition_delay">0dp</dimen>
+
+ <!-- Distance that it takes for the notifications scrim to fully fade if after it started. -->
+ <dimen name="lockscreen_shade_notifications_scrim_transition_distance">@dimen/lockscreen_shade_scrim_transition_distance</dimen>
+
<!-- Distance that the full shade transition takes in order for the keyguard content on
NotificationPanelViewController to fully fade (e.g. Clock & Smartspace) -->
<dimen name="lockscreen_shade_npvc_keyguard_content_alpha_transition_distance">@dimen/lockscreen_shade_full_transition_distance</dimen>
@@ -1376,6 +1388,7 @@
<dimen name="dream_overlay_complication_weather_text_size">18sp</dimen>
<dimen name="dream_overlay_complication_preview_text_size">36sp</dimen>
<dimen name="dream_overlay_complication_preview_icon_padding">28dp</dimen>
+ <dimen name="dream_overlay_complication_shadow_padding">2dp</dimen>
<!-- The position of the end guide, which dream overlay complications can align their start with
if their end is aligned with the parent end. Represented as the percentage over from the
diff --git a/packages/SystemUI/res/values/strings.xml b/packages/SystemUI/res/values/strings.xml
index d230f33..6dc6214 100644
--- a/packages/SystemUI/res/values/strings.xml
+++ b/packages/SystemUI/res/values/strings.xml
@@ -2184,7 +2184,7 @@
<!-- Text informing the user that their media is now playing on this device. [CHAR LIMIT=50] -->
<string name="media_transfer_playing_this_device">Playing on this phone</string>
<!-- Text informing the user that the media transfer has failed because something went wrong. [CHAR LIMIT=50] -->
- <string name="media_transfer_failed">Something went wrong</string>
+ <string name="media_transfer_failed">Something went wrong. Try again.</string>
<!-- Error message indicating that a control timed out while waiting for an update [CHAR_LIMIT=30] -->
<string name="controls_error_timeout">Inactive, check app</string>
diff --git a/packages/SystemUI/res/values/styles.xml b/packages/SystemUI/res/values/styles.xml
index 3ae21e0..f5c1382 100644
--- a/packages/SystemUI/res/values/styles.xml
+++ b/packages/SystemUI/res/values/styles.xml
@@ -486,7 +486,7 @@
<style name="MediaOutputItemInactiveTitle">
<item name="android:textSize">16sp</item>
- <item name="android:textColor">@color/media_dialog_inactive_item_main_content</item>
+ <item name="android:textColor">@color/media_dialog_item_main_content</item>
</style>
<style name="TunerSettings" parent="@android:style/Theme.DeviceDefault.Settings">
diff --git a/packages/SystemUI/src/com/android/keyguard/BouncerPanelExpansionCalculator.kt b/packages/SystemUI/src/com/android/keyguard/BouncerPanelExpansionCalculator.kt
new file mode 100644
index 0000000..497d81f
--- /dev/null
+++ b/packages/SystemUI/src/com/android/keyguard/BouncerPanelExpansionCalculator.kt
@@ -0,0 +1,49 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.keyguard
+
+import android.util.MathUtils
+
+object BouncerPanelExpansionCalculator {
+ /**
+ * Scale the alpha/position of the host view.
+ */
+ @JvmStatic
+ fun getHostViewScaledExpansion(fraction: Float): Float {
+ return when {
+ fraction >= 0.9f -> 1f
+ fraction < 0.6 -> 0f
+ else -> (fraction - 0.6f) / 0.3f
+ }
+ }
+
+ /**
+ * Scale the alpha/tint of the back scrim.
+ */
+ @JvmStatic
+ fun getBackScrimScaledExpansion(fraction: Float): Float {
+ return MathUtils.constrain((fraction - 0.9f) / 0.1f, 0f, 1f)
+ }
+
+ /**
+ * This will scale the alpha/position of the clock.
+ */
+ @JvmStatic
+ fun getKeyguardClockScaledExpansion(fraction: Float): Float {
+ return MathUtils.constrain((fraction - 0.7f) / 0.3f, 0f, 1f)
+ }
+}
\ No newline at end of file
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardHostViewController.java b/packages/SystemUI/src/com/android/keyguard/KeyguardHostViewController.java
index b691096..8c3e066 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardHostViewController.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardHostViewController.java
@@ -37,7 +37,6 @@
import com.android.settingslib.Utils;
import com.android.systemui.R;
import com.android.systemui.plugins.ActivityStarter;
-import com.android.systemui.statusbar.phone.KeyguardBouncer;
import com.android.systemui.util.ViewController;
import java.io.File;
@@ -64,6 +63,7 @@
private ActivityStarter.OnDismissAction mDismissAction;
private Runnable mCancelAction;
+ private int mTranslationY;
private final KeyguardUpdateMonitorCallback mUpdateCallback =
new KeyguardUpdateMonitorCallback() {
@@ -322,12 +322,14 @@
/**
* Fades and translates in/out the security screen.
+ * Fades in as expansion approaches 0.
+ * Animation duration is between 0.33f and 0.67f of panel expansion fraction.
* @param fraction amount of the screen that should show.
*/
public void setExpansion(float fraction) {
- float alpha = MathUtils.map(KeyguardBouncer.ALPHA_EXPANSION_THRESHOLD, 1, 1, 0, fraction);
- mView.setAlpha(MathUtils.constrain(alpha, 0f, 1f));
- mView.setTranslationY(fraction * mView.getHeight());
+ float scaledFraction = BouncerPanelExpansionCalculator.getHostViewScaledExpansion(fraction);
+ mView.setAlpha(MathUtils.constrain(1 - scaledFraction, 0f, 1f));
+ mView.setTranslationY(scaledFraction * mTranslationY);
}
/**
@@ -490,6 +492,8 @@
gravity = resources.getInteger(R.integer.keyguard_host_view_gravity);
}
+ mTranslationY = resources
+ .getDimensionPixelSize(R.dimen.keyguard_host_view_translation_y);
// Android SysUI uses a FrameLayout as the top-level, but Auto uses RelativeLayout.
// We're just changing the gravity here though (which can't be applied to RelativeLayout),
// so only attempt the update if mView is inside a FrameLayout.
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainer.java b/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainer.java
index 362fbed..46a88319 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainer.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainer.java
@@ -152,6 +152,7 @@
private SwipeListener mSwipeListener;
private ViewMode mViewMode = new DefaultViewMode();
private @Mode int mCurrentMode = MODE_DEFAULT;
+ private int mWidth = -1;
private final WindowInsetsAnimation.Callback mWindowInsetsAnimationCallback =
new WindowInsetsAnimation.Callback(DISPATCH_MODE_STOP) {
@@ -649,9 +650,11 @@
protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
super.onLayout(changed, left, top, right, bottom);
- // After a layout pass, we need to re-place the inner bouncer, as our bounds may have
- // changed.
- mViewMode.updateSecurityViewLocation();
+ int width = right - left;
+ if (changed && mWidth != width) {
+ mWidth = width;
+ mViewMode.updateSecurityViewLocation();
+ }
}
@Override
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java b/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java
index 1ef6dea..3858f9c 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java
@@ -326,7 +326,6 @@
private int mActiveMobileDataSubscription = SubscriptionManager.INVALID_SUBSCRIPTION_ID;
private final Executor mBackgroundExecutor;
private SensorPrivacyManager mSensorPrivacyManager;
- private int mFaceAuthUserId;
/**
* Short delay before restarting fingerprint authentication after a successful try. This should
@@ -1030,8 +1029,8 @@
boolean cameraPrivacyEnabled = false;
if (mSensorPrivacyManager != null) {
cameraPrivacyEnabled = mSensorPrivacyManager
- .isSensorPrivacyEnabled(SensorPrivacyManager.Sensors.CAMERA,
- mFaceAuthUserId);
+ .isSensorPrivacyEnabled(SensorPrivacyManager.TOGGLE_TYPE_SOFTWARE,
+ SensorPrivacyManager.Sensors.CAMERA);
}
if (msgId == FaceManager.FACE_ERROR_CANCELED
@@ -2599,7 +2598,6 @@
// This would need to be updated for multi-sensor devices
final boolean supportsFaceDetection = !mFaceSensorProperties.isEmpty()
&& mFaceSensorProperties.get(0).supportsFaceDetection;
- mFaceAuthUserId = userId;
if (isEncryptedOrLockdown(userId) && supportsFaceDetection) {
mFaceManager.detectFace(mFaceCancelSignal, mFaceDetectionCallback, userId);
} else {
diff --git a/packages/SystemUI/src/com/android/keyguard/LockIconViewController.java b/packages/SystemUI/src/com/android/keyguard/LockIconViewController.java
index 74659f7..e36e984 100644
--- a/packages/SystemUI/src/com/android/keyguard/LockIconViewController.java
+++ b/packages/SystemUI/src/com/android/keyguard/LockIconViewController.java
@@ -211,6 +211,23 @@
mDownDetected = false;
updateBurnInOffsets();
updateVisibility();
+
+ updateAccessibility();
+ }
+
+ private void updateAccessibility() {
+ if (mAccessibilityManager.isTouchExplorationEnabled()) {
+ mView.setOnClickListener(
+ new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ onLongPress();
+ }
+ }
+ );
+ } else {
+ mView.setOnClickListener(null);
+ }
}
@Override
diff --git a/packages/SystemUI/src/com/android/systemui/ScreenDecorHwcLayer.kt b/packages/SystemUI/src/com/android/systemui/ScreenDecorHwcLayer.kt
index 4b86862..498e715 100644
--- a/packages/SystemUI/src/com/android/systemui/ScreenDecorHwcLayer.kt
+++ b/packages/SystemUI/src/com/android/systemui/ScreenDecorHwcLayer.kt
@@ -119,9 +119,13 @@
if (useInvertedAlphaColor) {
canvas.drawColor(bgColor)
}
+
+ // We may clear the color(if useInvertedAlphaColor is true) of the rounded corner rects
+ // before drawing rounded corners. If the cutout happens to be inside one of these rects, it
+ // will be cleared, so we have to draw rounded corners before cutout.
+ drawRoundedCorners(canvas)
// Cutouts are drawn in DisplayCutoutBaseView.onDraw()
super.onDraw(canvas)
- drawRoundedCorners(canvas)
debugTransparentRegionPaint?.let {
calculateTransparentRect()
diff --git a/packages/SystemUI/src/com/android/systemui/accessibility/WindowMagnificationController.java b/packages/SystemUI/src/com/android/systemui/accessibility/WindowMagnificationController.java
index 7e1a026..807ff21 100644
--- a/packages/SystemUI/src/com/android/systemui/accessibility/WindowMagnificationController.java
+++ b/packages/SystemUI/src/com/android/systemui/accessibility/WindowMagnificationController.java
@@ -254,8 +254,8 @@
mMirrorViewGeometryVsyncCallback =
l -> {
- if (isWindowVisible() && mMirrorSurface != null) {
- calculateSourceBounds(mMagnificationFrame, mScale);
+ if (isWindowVisible() && mMirrorSurface != null && calculateSourceBounds(
+ mMagnificationFrame, mScale)) {
// The final destination for the magnification surface should be at 0,0
// since the ViewRootImpl's position will change
mTmpRect.set(0, 0, mMagnificationFrame.width(),
@@ -350,6 +350,7 @@
mMirrorWindowControl.destroyControl();
}
mMirrorViewBounds.setEmpty();
+ mSourceBounds.setEmpty();
updateSystemUIStateIfNeeded();
mContext.unregisterComponentCallbacks(this);
}
@@ -728,8 +729,12 @@
/**
* Calculates the desired source bounds. This will be the area under from the center of the
* displayFrame, factoring in scale.
+ *
+ * @return {@code true} if the source bounds is changed.
*/
- private void calculateSourceBounds(Rect displayFrame, float scale) {
+ private boolean calculateSourceBounds(Rect displayFrame, float scale) {
+ final Rect oldSourceBounds = mTmpRect;
+ oldSourceBounds.set(mSourceBounds);
int halfWidth = displayFrame.width() / 2;
int halfHeight = displayFrame.height() / 2;
int left = displayFrame.left + (halfWidth - (int) (halfWidth / scale));
@@ -757,6 +762,7 @@
mSourceBounds.offsetTo(mSourceBounds.left,
mWindowBounds.height() - mSourceBounds.height());
}
+ return !mSourceBounds.equals(oldSourceBounds);
}
private void calculateMagnificationFrameBoundary() {
@@ -1079,7 +1085,7 @@
pw.println(" mMagnificationFrame:"
+ (isWindowVisible() ? mMagnificationFrame : "empty"));
pw.println(" mSourceBounds:"
- + (isWindowVisible() ? mSourceBounds : "empty"));
+ + (mSourceBounds.isEmpty() ? "empty" : mSourceBounds));
pw.println(" mSystemGestureTop:" + mSystemGestureTop);
pw.println(" mMagnificationFrameOffsetX:" + mMagnificationFrameOffsetX);
pw.println(" mMagnificationFrameOffsetY:" + mMagnificationFrameOffsetY);
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/AuthController.java b/packages/SystemUI/src/com/android/systemui/biometrics/AuthController.java
index 64c2d2e..c100a07 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/AuthController.java
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/AuthController.java
@@ -726,8 +726,8 @@
boolean isCameraPrivacyEnabled = false;
if (error == BiometricConstants.BIOMETRIC_ERROR_HW_UNAVAILABLE
- && mSensorPrivacyManager.isSensorPrivacyEnabled(SensorPrivacyManager.Sensors.CAMERA,
- mCurrentDialogArgs.argi1 /* userId */)) {
+ && mSensorPrivacyManager.isSensorPrivacyEnabled(
+ SensorPrivacyManager.TOGGLE_TYPE_SOFTWARE, SensorPrivacyManager.Sensors.CAMERA)) {
isCameraPrivacyEnabled = true;
}
// TODO(b/141025588): Create separate methods for handling hard and soft errors.
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/AuthCredentialView.java b/packages/SystemUI/src/com/android/systemui/biometrics/AuthCredentialView.java
index 57ca0f4..2f2ca5b 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/AuthCredentialView.java
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/AuthCredentialView.java
@@ -20,7 +20,7 @@
import static android.app.admin.DevicePolicyResources.Strings.SystemUi.BIOMETRIC_DIALOG_WORK_PASSWORD_LAST_ATTEMPT;
import static android.app.admin.DevicePolicyResources.Strings.SystemUi.BIOMETRIC_DIALOG_WORK_PATTERN_LAST_ATTEMPT;
import static android.app.admin.DevicePolicyResources.Strings.SystemUi.BIOMETRIC_DIALOG_WORK_PIN_LAST_ATTEMPT;
-import static android.app.admin.DevicePolicyResources.Strings.UNDEFINED;
+import static android.app.admin.DevicePolicyResources.UNDEFINED;
import android.annotation.IntDef;
import android.annotation.NonNull;
@@ -442,7 +442,7 @@
private String getLastAttemptBeforeWipeProfileMessage(
@Utils.CredentialType int credentialType) {
- return mDevicePolicyManager.getString(
+ return mDevicePolicyManager.getResources().getString(
getLastAttemptBeforeWipeProfileUpdatableStringId(credentialType),
() -> getLastAttemptBeforeWipeProfileDefaultMessage(credentialType));
}
@@ -495,7 +495,7 @@
}
private String getNowWipingMessage(@UserType int userType) {
- return mDevicePolicyManager.getString(
+ return mDevicePolicyManager.getResources().getString(
getNowWipingUpdatableStringId(userType),
() -> getNowWipingDefaultMessage(userType));
}
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/AuthRippleController.kt b/packages/SystemUI/src/com/android/systemui/biometrics/AuthRippleController.kt
index a27b9cd..b811c51 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/AuthRippleController.kt
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/AuthRippleController.kt
@@ -116,7 +116,7 @@
}
fun showRipple(biometricSourceType: BiometricSourceType?) {
- if (!keyguardUpdateMonitor.isKeyguardVisible ||
+ if (!(keyguardUpdateMonitor.isKeyguardVisible || keyguardUpdateMonitor.isDreaming) ||
keyguardUpdateMonitor.userNeedsStrongAuth()) {
return
}
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsController.java b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsController.java
index bc7a3f6..975e0c5 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsController.java
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsController.java
@@ -49,7 +49,6 @@
import android.view.MotionEvent;
import android.view.Surface;
import android.view.VelocityTracker;
-import android.view.View;
import android.view.WindowManager;
import android.view.accessibility.AccessibilityManager;
@@ -92,7 +91,7 @@
* Note that the current architecture is designed so that a single {@link UdfpsController}
* controls/manages all UDFPS sensors. In other words, a single controller is registered with
* {@link com.android.server.biometrics.sensors.fingerprint.FingerprintService}, and interfaces such
- * as {@link FingerprintManager#onPointerDown(int, int, int, float, float)} or
+ * as {@link FingerprintManager#onPointerDown(long, int, int, int, float, float)} or
* {@link IUdfpsOverlayController#showUdfpsOverlay} should all have
* {@code sensorId} parameters.
*/
@@ -193,7 +192,7 @@
public class UdfpsOverlayController extends IUdfpsOverlayController.Stub {
@Override
- public void showUdfpsOverlay(int sensorId, int reason,
+ public void showUdfpsOverlay(long requestId, int sensorId, int reason,
@NonNull IUdfpsOverlayControllerCallback callback) {
mFgExecutor.execute(
() -> UdfpsController.this.showUdfpsOverlay(new UdfpsControllerOverlay(
@@ -203,8 +202,10 @@
mKeyguardUpdateMonitor, mDialogManager, mDumpManager,
mLockscreenShadeTransitionController, mConfigurationController,
mSystemClock, mKeyguardStateController,
- mUnlockedScreenOffAnimationController, mSensorProps, mHbmProvider,
- reason, callback, UdfpsController.this::onTouch,
+ mUnlockedScreenOffAnimationController, mSensorProps,
+ mHbmProvider, requestId, reason, callback,
+ (view, event, fromUdfpsView) ->
+ onTouch(requestId, event, fromUdfpsView),
mActivityLaunchAnimator)));
}
@@ -318,7 +319,8 @@
if (mOverlay == null || mOverlay.isHiding()) {
return false;
}
- return onTouch(mOverlay.getOverlayView(), event, false);
+ // TODO(b/225068271): may not be correct but no way to get the id yet
+ return onTouch(mOverlay.getRequestId(), event, false);
}
/**
@@ -342,8 +344,18 @@
&& getSensorLocation().contains(x, y);
}
- private boolean onTouch(@NonNull View view, @NonNull MotionEvent event, boolean fromUdfpsView) {
- UdfpsView udfpsView = (UdfpsView) view;
+ private boolean onTouch(long requestId, @NonNull MotionEvent event, boolean fromUdfpsView) {
+ if (mOverlay == null) {
+ Log.w(TAG, "ignoring onTouch with null overlay");
+ return false;
+ }
+ if (!mOverlay.matchesRequestId(requestId)) {
+ Log.w(TAG, "ignoring stale touch event: " + requestId + " current: "
+ + mOverlay.getRequestId());
+ return false;
+ }
+
+ final UdfpsView udfpsView = mOverlay.getOverlayView();
final boolean isIlluminationRequested = udfpsView.isIlluminationRequested();
boolean handled = false;
switch (event.getActionMasked()) {
@@ -453,7 +465,7 @@
// Do nothing to stay in portrait mode.
}
- onFingerDown(x, y, minor, major);
+ onFingerDown(requestId, x, y, minor, major);
Log.v(TAG, "onTouch | finger down: " + touchInfo);
mTouchLogTime = mSystemClock.elapsedRealtime();
mPowerManager.userActivity(mSystemClock.uptimeMillis(),
@@ -465,7 +477,7 @@
}
} else {
Log.v(TAG, "onTouch | finger outside");
- onFingerUp(udfpsView);
+ onFingerUp(requestId, udfpsView);
}
}
Trace.endSection();
@@ -482,7 +494,7 @@
}
Log.v(TAG, "onTouch | finger up");
mAttemptedToDismissKeyguard = false;
- onFingerUp(udfpsView);
+ onFingerUp(requestId, udfpsView);
mFalsingManager.isFalseTouch(UDFPS_AUTHENTICATION);
Trace.endSection();
break;
@@ -679,7 +691,7 @@
// Reset the controller back to its starting state.
final UdfpsView oldView = mOverlay.getOverlayView();
if (oldView != null) {
- onFingerUp(oldView);
+ onFingerUp(mOverlay.getRequestId(), oldView);
}
final boolean removed = mOverlay.hide();
if (mKeyguardViewManager.isShowingAlternateAuth()) {
@@ -710,6 +722,8 @@
return;
}
+ // TODO(b/225068271): this may not be correct but there isn't a way to track it
+ final long requestId = mOverlay != null ? mOverlay.getRequestId() : -1;
mAodInterruptRunnable = () -> {
mIsAodInterruptActive = true;
// Since the sensor that triggers the AOD interrupt doesn't provide
@@ -719,10 +733,10 @@
mCancelAodTimeoutAction = mFgExecutor.executeDelayed(this::onCancelUdfps,
AOD_INTERRUPT_TIMEOUT_MILLIS);
// using a hard-coded value for major and minor until it is available from the sensor
- onFingerDown(screenX, screenY, minor, major);
+ onFingerDown(requestId, screenX, screenY, minor, major);
};
- if (mScreenOn && mAodInterruptRunnable != null) {
+ if (mScreenOn) {
mAodInterruptRunnable.run();
mAodInterruptRunnable = null;
}
@@ -755,7 +769,7 @@
*/
void onCancelUdfps() {
if (mOverlay != null && mOverlay.getOverlayView() != null) {
- onFingerUp(mOverlay.getOverlayView());
+ onFingerUp(mOverlay.getRequestId(), mOverlay.getOverlayView());
}
if (!mIsAodInterruptActive) {
return;
@@ -771,12 +785,17 @@
return mOnFingerDown;
}
- private void onFingerDown(int x, int y, float minor, float major) {
+ private void onFingerDown(long requestId, int x, int y, float minor, float major) {
mExecution.assertIsMainThread();
if (mOverlay == null) {
Log.w(TAG, "Null request in onFingerDown");
return;
}
+ if (!mOverlay.matchesRequestId(requestId)) {
+ Log.w(TAG, "Mismatched fingerDown: " + requestId
+ + " current: " + mOverlay.getRequestId());
+ return;
+ }
if (mOverlay.getAnimationViewController() instanceof UdfpsKeyguardViewController
&& !mStatusBarStateController.isDozing()) {
@@ -791,14 +810,14 @@
}
}
mOnFingerDown = true;
- mFingerprintManager.onPointerDown(mSensorProps.sensorId, x, y, minor, major);
+ mFingerprintManager.onPointerDown(requestId, mSensorProps.sensorId, x, y, minor, major);
Trace.endAsyncSection("UdfpsController.e2e.onPointerDown", 0);
final UdfpsView view = mOverlay.getOverlayView();
if (view != null) {
Trace.beginAsyncSection("UdfpsController.e2e.startIllumination", 0);
view.startIllumination(() -> {
- mFingerprintManager.onUiReady(mSensorProps.sensorId);
+ mFingerprintManager.onUiReady(requestId, mSensorProps.sensorId);
mLatencyTracker.onActionEnd(LatencyTracker.ACTION_UDFPS_ILLUMINATE);
Trace.endAsyncSection("UdfpsController.e2e.startIllumination", 0);
});
@@ -809,12 +828,12 @@
}
}
- private void onFingerUp(@NonNull UdfpsView view) {
+ private void onFingerUp(long requestId, @NonNull UdfpsView view) {
mExecution.assertIsMainThread();
mActivePointerId = -1;
mAcquiredReceived = false;
if (mOnFingerDown) {
- mFingerprintManager.onPointerUp(mSensorProps.sensorId);
+ mFingerprintManager.onPointerUp(requestId, mSensorProps.sensorId);
for (Callback cb : mCallbacks) {
cb.onFingerUp();
}
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsControllerOverlay.kt b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsControllerOverlay.kt
index 086894d..ee43e93 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsControllerOverlay.kt
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsControllerOverlay.kt
@@ -80,6 +80,7 @@
private val unlockedScreenOffAnimationController: UnlockedScreenOffAnimationController,
private val sensorProps: FingerprintSensorPropertiesInternal,
private var hbmProvider: UdfpsHbmProvider,
+ val requestId: Long,
@ShowReason val requestReason: Int,
private val controllerCallback: IUdfpsOverlayControllerCallback,
private val onTouch: (View, MotionEvent, Boolean) -> Boolean,
@@ -276,6 +277,9 @@
}
}
+ /** Checks if the id is relevant for this overlay. */
+ fun matchesRequestId(id: Long): Boolean = requestId == -1L || requestId == id
+
private fun WindowManager.LayoutParams.updateForLocation(
location: SensorLocationInternal,
animation: UdfpsAnimationViewController<*>?
diff --git a/packages/SystemUI/src/com/android/systemui/dagger/SystemUICoreStartableModule.kt b/packages/SystemUI/src/com/android/systemui/dagger/SystemUICoreStartableModule.kt
index f78929f..a9f34085 100644
--- a/packages/SystemUI/src/com/android/systemui/dagger/SystemUICoreStartableModule.kt
+++ b/packages/SystemUI/src/com/android/systemui/dagger/SystemUICoreStartableModule.kt
@@ -35,6 +35,7 @@
import com.android.systemui.recents.Recents
import com.android.systemui.shortcut.ShortcutKeyDispatcher
import com.android.systemui.statusbar.notification.InstantAppNotifier
+import com.android.systemui.statusbar.phone.KeyguardLiftController
import com.android.systemui.theme.ThemeOverlayController
import com.android.systemui.toast.ToastUI
import com.android.systemui.usb.StorageNotification
@@ -198,4 +199,10 @@
@IntoMap
@ClassKey(WMShell::class)
abstract fun bindWMShell(sysui: WMShell): CoreStartable
+
+ /** Inject into KeyguardLiftController. */
+ @Binds
+ @IntoMap
+ @ClassKey(KeyguardLiftController::class)
+ abstract fun bindKeyguardLiftController(sysui: KeyguardLiftController): CoreStartable
}
\ No newline at end of file
diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeScreenBrightness.java b/packages/SystemUI/src/com/android/systemui/doze/DozeScreenBrightness.java
index b8b4092..dfb27ef 100644
--- a/packages/SystemUI/src/com/android/systemui/doze/DozeScreenBrightness.java
+++ b/packages/SystemUI/src/com/android/systemui/doze/DozeScreenBrightness.java
@@ -89,6 +89,7 @@
private boolean mPaused = false;
private boolean mScreenOff = false;
private int mLastSensorValue = -1;
+ private DozeMachine.State mState = DozeMachine.State.UNINITIALIZED;
/**
* Debug value used for emulating various display brightness buckets:
@@ -135,6 +136,7 @@
@Override
public void transitionTo(DozeMachine.State oldState, DozeMachine.State newState) {
+ mState = newState;
switch (newState) {
case INITIALIZED:
resetBrightnessToDefault();
@@ -262,8 +264,9 @@
*/
private int clampToDimBrightnessForScreenOff(int brightness) {
final boolean screenTurningOff =
- mDozeParameters.shouldClampToDimBrightness()
- || mWakefulnessLifecycle.getWakefulness() == WAKEFULNESS_GOING_TO_SLEEP;
+ (mDozeParameters.shouldClampToDimBrightness()
+ || mWakefulnessLifecycle.getWakefulness() == WAKEFULNESS_GOING_TO_SLEEP)
+ && mState == DozeMachine.State.INITIALIZED;
if (screenTurningOff
&& mWakefulnessLifecycle.getLastSleepReason() == GO_TO_SLEEP_REASON_TIMEOUT) {
return Math.max(
diff --git a/packages/SystemUI/src/com/android/systemui/dreams/DreamOverlayStatusBarView.java b/packages/SystemUI/src/com/android/systemui/dreams/DreamOverlayStatusBarView.java
index d2ab611..59a17ba 100644
--- a/packages/SystemUI/src/com/android/systemui/dreams/DreamOverlayStatusBarView.java
+++ b/packages/SystemUI/src/com/android/systemui/dreams/DreamOverlayStatusBarView.java
@@ -88,10 +88,6 @@
fetchStatusIconForResId(R.id.dream_overlay_priority_mode));
}
- void showIcon(@StatusIconType int iconType, boolean show) {
- showIcon(iconType, show, null);
- }
-
void showIcon(@StatusIconType int iconType, boolean show, @Nullable String contentDescription) {
View icon = mStatusIcons.get(iconType);
if (icon == null) {
diff --git a/packages/SystemUI/src/com/android/systemui/dreams/DreamOverlayStatusBarViewController.java b/packages/SystemUI/src/com/android/systemui/dreams/DreamOverlayStatusBarViewController.java
index a25a742..761f28c 100644
--- a/packages/SystemUI/src/com/android/systemui/dreams/DreamOverlayStatusBarViewController.java
+++ b/packages/SystemUI/src/com/android/systemui/dreams/DreamOverlayStatusBarViewController.java
@@ -16,6 +16,7 @@
package com.android.systemui.dreams;
+import android.annotation.Nullable;
import android.app.AlarmManager;
import android.content.res.Resources;
import android.hardware.SensorPrivacyManager;
@@ -45,6 +46,7 @@
import java.util.Locale;
import java.util.Map;
+import java.util.concurrent.Executor;
import javax.inject.Inject;
@@ -62,6 +64,9 @@
private final IndividualSensorPrivacyController mSensorPrivacyController;
private final NotificationListener mNotificationListener;
private final ZenModeController mZenModeController;
+ private final Executor mMainExecutor;
+
+ private boolean mIsAttached;
private final NetworkRequest mNetworkRequest = new NetworkRequest.Builder()
.clearCapabilities()
@@ -131,6 +136,7 @@
public DreamOverlayStatusBarViewController(
DreamOverlayStatusBarView view,
@Main Resources resources,
+ @Main Executor mainExecutor,
ConnectivityManager connectivityManager,
TouchInsetManager.TouchInsetSession touchInsetSession,
AlarmManager alarmManager,
@@ -141,6 +147,7 @@
ZenModeController zenModeController) {
super(view);
mResources = resources;
+ mMainExecutor = mainExecutor;
mConnectivityManager = connectivityManager;
mTouchInsetSession = touchInsetSession;
mAlarmManager = alarmManager;
@@ -157,6 +164,8 @@
@Override
protected void onViewAttached() {
+ mIsAttached = true;
+
updateNotificationsStatusIcon();
mConnectivityManager.registerNetworkCallback(mNetworkRequest, mNetworkCallback);
@@ -181,6 +190,8 @@
mNextAlarmController.removeCallback(mNextAlarmCallback);
mConnectivityManager.unregisterNetworkCallback(mNetworkCallback);
mTouchInsetSession.clear();
+
+ mIsAttached = false;
}
private void updateWifiUnavailableStatusIcon() {
@@ -189,14 +200,14 @@
mConnectivityManager.getActiveNetwork());
final boolean available = capabilities != null
&& capabilities.hasTransport(NetworkCapabilities.TRANSPORT_WIFI);
- mView.showIcon(DreamOverlayStatusBarView.STATUS_ICON_WIFI_UNAVAILABLE, !available);
+ showIcon(DreamOverlayStatusBarView.STATUS_ICON_WIFI_UNAVAILABLE, !available);
}
private void updateAlarmStatusIcon() {
final AlarmManager.AlarmClockInfo alarm =
mAlarmManager.getNextAlarmClock(UserHandle.USER_CURRENT);
final boolean hasAlarm = alarm != null && alarm.getTriggerTime() > 0;
- mView.showIcon(
+ showIcon(
DreamOverlayStatusBarView.STATUS_ICON_ALARM_SET,
hasAlarm,
hasAlarm ? buildAlarmContentDescription(alarm) : null);
@@ -215,7 +226,7 @@
.isSensorBlocked(SensorPrivacyManager.Sensors.MICROPHONE);
final boolean cameraBlocked = mSensorPrivacyController
.isSensorBlocked(SensorPrivacyManager.Sensors.CAMERA);
- mView.showIcon(
+ showIcon(
DreamOverlayStatusBarView.STATUS_ICON_MIC_CAMERA_DISABLED,
micBlocked && cameraBlocked);
}
@@ -230,7 +241,7 @@
final StatusBarNotification[] notifications =
mNotificationListener.getActiveNotifications();
final int notificationCount = notifications != null ? notifications.length : 0;
- mView.showIcon(
+ showIcon(
DreamOverlayStatusBarView.STATUS_ICON_NOTIFICATIONS,
notificationCount > 0,
notificationCount > 0
@@ -246,8 +257,23 @@
}
private void updatePriorityModeStatusIcon() {
- mView.showIcon(
+ showIcon(
DreamOverlayStatusBarView.STATUS_ICON_PRIORITY_MODE_ON,
mZenModeController.getZen() != Settings.Global.ZEN_MODE_OFF);
}
+
+ private void showIcon(@DreamOverlayStatusBarView.StatusIconType int iconType, boolean show) {
+ showIcon(iconType, show, null);
+ }
+
+ private void showIcon(
+ @DreamOverlayStatusBarView.StatusIconType int iconType,
+ boolean show,
+ @Nullable String contentDescription) {
+ mMainExecutor.execute(() -> {
+ if (mIsAttached) {
+ mView.showIcon(iconType, show, contentDescription);
+ }
+ });
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/dreams/complication/DreamClockDateComplication.java b/packages/SystemUI/src/com/android/systemui/dreams/complication/DreamClockDateComplication.java
index 6861c74..1ca06b2 100644
--- a/packages/SystemUI/src/com/android/systemui/dreams/complication/DreamClockDateComplication.java
+++ b/packages/SystemUI/src/com/android/systemui/dreams/complication/DreamClockDateComplication.java
@@ -16,32 +16,32 @@
package com.android.systemui.dreams.complication;
-import static com.android.systemui.dreams.complication.dagger.DreamClockDateComplicationComponent.DreamClockDateComplicationModule.DREAM_CLOCK_DATE_COMPLICATION_LAYOUT_PARAMS;
-import static com.android.systemui.dreams.complication.dagger.DreamClockDateComplicationComponent.DreamClockDateComplicationModule.DREAM_CLOCK_DATE_COMPLICATION_VIEW;
+import static com.android.systemui.dreams.complication.dagger.DreamClockDateComplicationModule.DREAM_CLOCK_DATE_COMPLICATION_LAYOUT_PARAMS;
+import static com.android.systemui.dreams.complication.dagger.DreamClockDateComplicationModule.DREAM_CLOCK_DATE_COMPLICATION_VIEW;
import android.content.Context;
import android.view.View;
import com.android.systemui.CoreStartable;
import com.android.systemui.dreams.DreamOverlayStateController;
-import com.android.systemui.dreams.complication.dagger.DreamClockDateComplicationComponent;
import javax.inject.Inject;
import javax.inject.Named;
+import javax.inject.Provider;
/**
* Clock Date Complication that produce Clock Date view holder.
*/
public class DreamClockDateComplication implements Complication {
- DreamClockDateComplicationComponent.Factory mComponentFactory;
+ private final Provider<DreamClockDateViewHolder> mDreamClockDateViewHolderProvider;
/**
* Default constructor for {@link DreamClockDateComplication}.
*/
@Inject
public DreamClockDateComplication(
- DreamClockDateComplicationComponent.Factory componentFactory) {
- mComponentFactory = componentFactory;
+ Provider<DreamClockDateViewHolder> dreamClockDateViewHolderProvider) {
+ mDreamClockDateViewHolderProvider = dreamClockDateViewHolderProvider;
}
@Override
@@ -54,11 +54,11 @@
*/
@Override
public ViewHolder createView(ComplicationViewModel model) {
- return mComponentFactory.create().getViewHolder();
+ return mDreamClockDateViewHolderProvider.get();
}
/**
- * {@link CoreStartable} responsbile for registering {@link DreamClockDateComplication} with
+ * {@link CoreStartable} responsible for registering {@link DreamClockDateComplication} with
* SystemUI.
*/
public static class Registrant extends CoreStartable {
@@ -84,7 +84,7 @@
}
/**
- * ViewHolder to contain value/logic associated with a Clock Date Complication View.
+ * {@link ViewHolder} to contain value/logic associated with {@link DreamClockDateComplication}.
*/
public static class DreamClockDateViewHolder implements ViewHolder {
private final View mView;
diff --git a/packages/SystemUI/src/com/android/systemui/dreams/complication/DreamClockTimeComplication.java b/packages/SystemUI/src/com/android/systemui/dreams/complication/DreamClockTimeComplication.java
index 936767a..7f67ecd 100644
--- a/packages/SystemUI/src/com/android/systemui/dreams/complication/DreamClockTimeComplication.java
+++ b/packages/SystemUI/src/com/android/systemui/dreams/complication/DreamClockTimeComplication.java
@@ -16,32 +16,32 @@
package com.android.systemui.dreams.complication;
-import static com.android.systemui.dreams.complication.dagger.DreamClockTimeComplicationComponent.DreamClockTimeComplicationModule.DREAM_CLOCK_TIME_COMPLICATION_LAYOUT_PARAMS;
-import static com.android.systemui.dreams.complication.dagger.DreamClockTimeComplicationComponent.DreamClockTimeComplicationModule.DREAM_CLOCK_TIME_COMPLICATION_VIEW;
+import static com.android.systemui.dreams.complication.dagger.DreamClockTimeComplicationModule.DREAM_CLOCK_TIME_COMPLICATION_LAYOUT_PARAMS;
+import static com.android.systemui.dreams.complication.dagger.DreamClockTimeComplicationModule.DREAM_CLOCK_TIME_COMPLICATION_VIEW;
import android.content.Context;
import android.view.View;
import com.android.systemui.CoreStartable;
import com.android.systemui.dreams.DreamOverlayStateController;
-import com.android.systemui.dreams.complication.dagger.DreamClockTimeComplicationComponent;
import javax.inject.Inject;
import javax.inject.Named;
+import javax.inject.Provider;
/**
* Clock Time Complication that produce Clock Time view holder.
*/
public class DreamClockTimeComplication implements Complication {
- DreamClockTimeComplicationComponent.Factory mComponentFactory;
+ private final Provider<DreamClockTimeViewHolder> mDreamClockTimeViewHolderProvider;
/**
* Default constructor for {@link DreamClockTimeComplication}.
*/
@Inject
public DreamClockTimeComplication(
- DreamClockTimeComplicationComponent.Factory componentFactory) {
- mComponentFactory = componentFactory;
+ Provider<DreamClockTimeViewHolder> dreamClockTimeViewHolderProvider) {
+ mDreamClockTimeViewHolderProvider = dreamClockTimeViewHolderProvider;
}
@Override
@@ -54,11 +54,11 @@
*/
@Override
public ViewHolder createView(ComplicationViewModel model) {
- return mComponentFactory.create().getViewHolder();
+ return mDreamClockTimeViewHolderProvider.get();
}
/**
- * {@link CoreStartable} responsbile for registering {@link DreamClockTimeComplication} with
+ * {@link CoreStartable} responsible for registering {@link DreamClockTimeComplication} with
* SystemUI.
*/
public static class Registrant extends CoreStartable {
@@ -84,7 +84,7 @@
}
/**
- * ViewHolder to contain value/logic associated with a Clock Time Complication View.
+ * {@link ViewHolder} to contain value/logic associated with {@link DreamClockTimeComplication}.
*/
public static class DreamClockTimeViewHolder implements ViewHolder {
private final View mView;
diff --git a/packages/SystemUI/src/com/android/systemui/dreams/complication/dagger/DreamClockDateComplicationComponent.java b/packages/SystemUI/src/com/android/systemui/dreams/complication/dagger/DreamClockDateComplicationComponent.java
deleted file mode 100644
index dd7f10c..0000000
--- a/packages/SystemUI/src/com/android/systemui/dreams/complication/dagger/DreamClockDateComplicationComponent.java
+++ /dev/null
@@ -1,110 +0,0 @@
-/*
- * Copyright (C) 2022 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.systemui.dreams.complication.dagger;
-
-
-import static java.lang.annotation.RetentionPolicy.RUNTIME;
-
-import android.view.LayoutInflater;
-import android.view.View;
-import android.view.ViewGroup;
-
-import com.android.internal.util.Preconditions;
-import com.android.systemui.R;
-import com.android.systemui.dreams.complication.ComplicationLayoutParams;
-import com.android.systemui.dreams.complication.DreamClockDateComplication.DreamClockDateViewHolder;
-
-import java.lang.annotation.Documented;
-import java.lang.annotation.Retention;
-
-import javax.inject.Named;
-import javax.inject.Scope;
-
-import dagger.Module;
-import dagger.Provides;
-import dagger.Subcomponent;
-
-/**
- * {@link DreamClockDateComplicationComponent} is responsible for generating dependencies
- * surrounding the
- * Clock Date {@link com.android.systemui.dreams.complication.Complication}, such as the layout
- * details.
- */
-@Subcomponent(modules = {
- DreamClockDateComplicationComponent.DreamClockDateComplicationModule.class,
-})
-@DreamClockDateComplicationComponent.DreamClockDateComplicationScope
-public interface DreamClockDateComplicationComponent {
- /**
- * Creates {@link DreamClockDateViewHolder}.
- */
- DreamClockDateViewHolder getViewHolder();
-
- @Documented
- @Retention(RUNTIME)
- @Scope
- @interface DreamClockDateComplicationScope {
- }
-
- /**
- * Generates {@link DreamClockDateComplicationComponent}.
- */
- @Subcomponent.Factory
- interface Factory {
- DreamClockDateComplicationComponent create();
- }
-
- /**
- * Scoped values for {@link DreamClockDateComplicationComponent}.
- */
- @Module
- interface DreamClockDateComplicationModule {
- String DREAM_CLOCK_DATE_COMPLICATION_VIEW = "clock_date_complication_view";
- String DREAM_CLOCK_DATE_COMPLICATION_LAYOUT_PARAMS =
- "clock_date_complication_layout_params";
- // Order weight of insert into parent container
- int INSERT_ORDER_WEIGHT = 2;
-
- /**
- * Provides the complication view.
- */
- @Provides
- @DreamClockDateComplicationScope
- @Named(DREAM_CLOCK_DATE_COMPLICATION_VIEW)
- static View provideComplicationView(LayoutInflater layoutInflater) {
- return Preconditions.checkNotNull(
- layoutInflater.inflate(R.layout.dream_overlay_complication_clock_date,
- null, false),
- "R.layout.dream_overlay_complication_clock_date did not properly inflated");
- }
-
- /**
- * Provides the layout parameters for the complication view.
- */
- @Provides
- @DreamClockDateComplicationScope
- @Named(DREAM_CLOCK_DATE_COMPLICATION_LAYOUT_PARAMS)
- static ComplicationLayoutParams provideLayoutParams() {
- return new ComplicationLayoutParams(0,
- ViewGroup.LayoutParams.WRAP_CONTENT,
- ComplicationLayoutParams.POSITION_BOTTOM
- | ComplicationLayoutParams.POSITION_START,
- ComplicationLayoutParams.DIRECTION_END,
- INSERT_ORDER_WEIGHT);
- }
- }
-}
diff --git a/packages/SystemUI/src/com/android/systemui/dreams/complication/dagger/DreamClockDateComplicationModule.java b/packages/SystemUI/src/com/android/systemui/dreams/complication/dagger/DreamClockDateComplicationModule.java
new file mode 100644
index 0000000..eb2fc5d
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/dreams/complication/dagger/DreamClockDateComplicationModule.java
@@ -0,0 +1,71 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.dreams.complication.dagger;
+
+
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+
+import com.android.internal.util.Preconditions;
+import com.android.systemui.R;
+import com.android.systemui.dreams.complication.ComplicationLayoutParams;
+import com.android.systemui.dreams.complication.DreamClockDateComplication;
+
+import javax.inject.Named;
+
+import dagger.Module;
+import dagger.Provides;
+
+/**
+ * Module for providing {@link DreamClockDateComplication}.
+ */
+@Module
+public interface DreamClockDateComplicationModule {
+ String DREAM_CLOCK_DATE_COMPLICATION_VIEW = "clock_date_complication_view";
+ String DREAM_CLOCK_DATE_COMPLICATION_LAYOUT_PARAMS =
+ "clock_date_complication_layout_params";
+ // Order weight of insert into parent container
+ //TODO(b/217199227): move to a single location.
+ int INSERT_ORDER_WEIGHT = 2;
+
+ /**
+ * Provides the complication view.
+ */
+ @Provides
+ @Named(DREAM_CLOCK_DATE_COMPLICATION_VIEW)
+ static View provideComplicationView(LayoutInflater layoutInflater) {
+ return Preconditions.checkNotNull(
+ layoutInflater.inflate(R.layout.dream_overlay_complication_clock_date,
+ null, false),
+ "R.layout.dream_overlay_complication_clock_date did not properly inflated");
+ }
+
+ /**
+ * Provides the layout parameters for the complication view.
+ */
+ @Provides
+ @Named(DREAM_CLOCK_DATE_COMPLICATION_LAYOUT_PARAMS)
+ static ComplicationLayoutParams provideLayoutParams() {
+ return new ComplicationLayoutParams(0,
+ ViewGroup.LayoutParams.WRAP_CONTENT,
+ ComplicationLayoutParams.POSITION_BOTTOM
+ | ComplicationLayoutParams.POSITION_START,
+ ComplicationLayoutParams.DIRECTION_END,
+ INSERT_ORDER_WEIGHT);
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/dreams/complication/dagger/DreamClockTimeComplicationComponent.java b/packages/SystemUI/src/com/android/systemui/dreams/complication/dagger/DreamClockTimeComplicationComponent.java
deleted file mode 100644
index de11b61..0000000
--- a/packages/SystemUI/src/com/android/systemui/dreams/complication/dagger/DreamClockTimeComplicationComponent.java
+++ /dev/null
@@ -1,115 +0,0 @@
-/*
- * Copyright (C) 2022 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.systemui.dreams.complication.dagger;
-
-
-import static java.lang.annotation.RetentionPolicy.RUNTIME;
-
-import android.view.LayoutInflater;
-import android.view.View;
-import android.view.ViewGroup;
-import android.widget.TextClock;
-
-import com.android.internal.util.Preconditions;
-import com.android.systemui.R;
-import com.android.systemui.dreams.complication.ComplicationLayoutParams;
-import com.android.systemui.dreams.complication.DreamClockTimeComplication.DreamClockTimeViewHolder;
-
-import java.lang.annotation.Documented;
-import java.lang.annotation.Retention;
-
-import javax.inject.Named;
-import javax.inject.Scope;
-
-import dagger.Module;
-import dagger.Provides;
-import dagger.Subcomponent;
-
-/**
- * {@link DreamClockTimeComplicationComponent} is responsible for generating dependencies
- * surrounding the
- * Clock Time {@link com.android.systemui.dreams.complication.Complication}, such as the layout
- * details.
- */
-@Subcomponent(modules = {
- DreamClockTimeComplicationComponent.DreamClockTimeComplicationModule.class,
-})
-@DreamClockTimeComplicationComponent.DreamClockTimeComplicationScope
-public interface DreamClockTimeComplicationComponent {
- /**
- * Creates {@link DreamClockTimeViewHolder}.
- */
- DreamClockTimeViewHolder getViewHolder();
-
- @Documented
- @Retention(RUNTIME)
- @Scope
- @interface DreamClockTimeComplicationScope {
- }
-
- /**
- * Generates {@link DreamClockTimeComplicationComponent}.
- */
- @Subcomponent.Factory
- interface Factory {
- DreamClockTimeComplicationComponent create();
- }
-
- /**
- * Scoped values for {@link DreamClockTimeComplicationComponent}.
- */
- @Module
- interface DreamClockTimeComplicationModule {
- String DREAM_CLOCK_TIME_COMPLICATION_VIEW = "clock_time_complication_view";
- String DREAM_CLOCK_TIME_COMPLICATION_LAYOUT_PARAMS =
- "clock_time_complication_layout_params";
- // Order weight of insert into parent container
- int INSERT_ORDER_WEIGHT = 0;
- String TAG_WEIGHT = "'wght' ";
- int WEIGHT = 200;
-
- /**
- * Provides the complication view.
- */
- @Provides
- @DreamClockTimeComplicationScope
- @Named(DREAM_CLOCK_TIME_COMPLICATION_VIEW)
- static View provideComplicationView(LayoutInflater layoutInflater) {
- final TextClock view = Preconditions.checkNotNull((TextClock)
- layoutInflater.inflate(R.layout.dream_overlay_complication_clock_time,
- null, false),
- "R.layout.dream_overlay_complication_clock_time did not properly inflated");
- view.setFontVariationSettings(TAG_WEIGHT + WEIGHT);
- return view;
- }
-
- /**
- * Provides the layout parameters for the complication view.
- */
- @Provides
- @DreamClockTimeComplicationScope
- @Named(DREAM_CLOCK_TIME_COMPLICATION_LAYOUT_PARAMS)
- static ComplicationLayoutParams provideLayoutParams() {
- return new ComplicationLayoutParams(0,
- ViewGroup.LayoutParams.WRAP_CONTENT,
- ComplicationLayoutParams.POSITION_BOTTOM
- | ComplicationLayoutParams.POSITION_START,
- ComplicationLayoutParams.DIRECTION_UP,
- INSERT_ORDER_WEIGHT);
- }
- }
-}
diff --git a/packages/SystemUI/src/com/android/systemui/dreams/complication/dagger/DreamClockTimeComplicationModule.java b/packages/SystemUI/src/com/android/systemui/dreams/complication/dagger/DreamClockTimeComplicationModule.java
new file mode 100644
index 0000000..3ad7d3d
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/dreams/complication/dagger/DreamClockTimeComplicationModule.java
@@ -0,0 +1,76 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.dreams.complication.dagger;
+
+
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.TextClock;
+
+import com.android.internal.util.Preconditions;
+import com.android.systemui.R;
+import com.android.systemui.dreams.complication.ComplicationLayoutParams;
+import com.android.systemui.dreams.complication.DreamClockTimeComplication;
+
+import javax.inject.Named;
+
+import dagger.Module;
+import dagger.Provides;
+
+/**
+ * Module for providing {@link DreamClockTimeComplication}.
+ */
+@Module
+public interface DreamClockTimeComplicationModule {
+ String DREAM_CLOCK_TIME_COMPLICATION_VIEW = "clock_time_complication_view";
+ String DREAM_CLOCK_TIME_COMPLICATION_LAYOUT_PARAMS =
+ "clock_time_complication_layout_params";
+ // Order weight of insert into parent container
+ //TODO(b/217199227): move to a single location.
+ int INSERT_ORDER_WEIGHT = 0;
+ String TAG_WEIGHT = "'wght' ";
+ int WEIGHT = 200;
+
+ /**
+ * Provides the complication view.
+ */
+ @Provides
+ @Named(DREAM_CLOCK_TIME_COMPLICATION_VIEW)
+ static View provideComplicationView(LayoutInflater layoutInflater) {
+ final TextClock view = Preconditions.checkNotNull((TextClock)
+ layoutInflater.inflate(R.layout.dream_overlay_complication_clock_time,
+ null, false),
+ "R.layout.dream_overlay_complication_clock_time did not properly inflated");
+ view.setFontVariationSettings(TAG_WEIGHT + WEIGHT);
+ return view;
+ }
+
+ /**
+ * Provides the layout parameters for the complication view.
+ */
+ @Provides
+ @Named(DREAM_CLOCK_TIME_COMPLICATION_LAYOUT_PARAMS)
+ static ComplicationLayoutParams provideLayoutParams() {
+ return new ComplicationLayoutParams(0,
+ ViewGroup.LayoutParams.WRAP_CONTENT,
+ ComplicationLayoutParams.POSITION_BOTTOM
+ | ComplicationLayoutParams.POSITION_START,
+ ComplicationLayoutParams.DIRECTION_UP,
+ INSERT_ORDER_WEIGHT);
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/dreams/complication/dagger/RegisteredComplicationsModule.java b/packages/SystemUI/src/com/android/systemui/dreams/complication/dagger/RegisteredComplicationsModule.java
index 8e4fb37..62a4140 100644
--- a/packages/SystemUI/src/com/android/systemui/dreams/complication/dagger/RegisteredComplicationsModule.java
+++ b/packages/SystemUI/src/com/android/systemui/dreams/complication/dagger/RegisteredComplicationsModule.java
@@ -24,10 +24,12 @@
* Module for all components with corresponding dream layer complications registered in
* {@link SystemUIBinder}.
*/
-@Module(subcomponents = {
- DreamClockTimeComplicationComponent.class,
- DreamClockDateComplicationComponent.class,
- DreamWeatherComplicationComponent.class,
-})
+@Module(includes = {
+ DreamClockDateComplicationModule.class,
+ DreamClockTimeComplicationModule.class,
+ },
+ subcomponents = {
+ DreamWeatherComplicationComponent.class,
+ })
public interface RegisteredComplicationsModule {
}
diff --git a/packages/SystemUI/src/com/android/systemui/flags/Flags.java b/packages/SystemUI/src/com/android/systemui/flags/Flags.java
index 2db3de1..61cfe92 100644
--- a/packages/SystemUI/src/com/android/systemui/flags/Flags.java
+++ b/packages/SystemUI/src/com/android/systemui/flags/Flags.java
@@ -145,7 +145,7 @@
/***************************************/
// 900 - media
public static final BooleanFlag MEDIA_TAP_TO_TRANSFER = new BooleanFlag(900, true);
- public static final BooleanFlag MEDIA_SESSION_ACTIONS = new BooleanFlag(901, true);
+ public static final BooleanFlag MEDIA_SESSION_ACTIONS = new BooleanFlag(901, false);
public static final BooleanFlag MEDIA_SESSION_LAYOUT = new BooleanFlag(902, true);
public static final BooleanFlag MEDIA_NEARBY_DEVICES = new BooleanFlag(903, true);
public static final BooleanFlag MEDIA_MUTE_AWAIT = new BooleanFlag(904, true);
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
index c01d2c3..bf464ec 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
@@ -20,6 +20,7 @@
import static android.view.WindowManagerPolicyConstants.KEYGUARD_GOING_AWAY_FLAG_WITH_WALLPAPER;
import static com.android.internal.config.sysui.SystemUiDeviceConfigFlags.NAV_BAR_HANDLE_SHOW_OVER_LOCKSCREEN;
+import static com.android.internal.jank.InteractionJankMonitor.CUJ_LOCKSCREEN_TRANSITION_FROM_AOD;
import static com.android.internal.jank.InteractionJankMonitor.CUJ_LOCKSCREEN_UNLOCK_ANIMATION;
import static com.android.internal.widget.LockPatternUtils.StrongAuthTracker.SOME_AUTH_REQUIRED_AFTER_USER_REQUEST;
import static com.android.internal.widget.LockPatternUtils.StrongAuthTracker.STRONG_AUTH_REQUIRED_AFTER_DPM_LOCK_NOW;
@@ -123,11 +124,11 @@
import com.android.systemui.statusbar.NotificationShadeWindowController;
import com.android.systemui.statusbar.SysuiStatusBarStateController;
import com.android.systemui.statusbar.phone.BiometricUnlockController;
+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.NotificationPanelViewController;
import com.android.systemui.statusbar.phone.ScreenOffAnimationController;
-import com.android.systemui.statusbar.phone.CentralSurfaces;
import com.android.systemui.statusbar.phone.panelstate.PanelExpansionStateManager;
import com.android.systemui.statusbar.policy.KeyguardStateController;
import com.android.systemui.statusbar.policy.UserSwitcherController;
@@ -1557,6 +1558,7 @@
public void setOccluded(boolean isOccluded, boolean animate) {
Trace.beginSection("KeyguardViewMediator#setOccluded");
if (DEBUG) Log.d(TAG, "setOccluded " + isOccluded);
+ mInteractionJankMonitor.cancel(CUJ_LOCKSCREEN_TRANSITION_FROM_AOD);
mHandler.removeMessages(SET_OCCLUDED);
Message msg = mHandler.obtainMessage(SET_OCCLUDED, isOccluded ? 1 : 0, animate ? 1 : 0);
mHandler.sendMessage(msg);
@@ -1706,14 +1708,6 @@
if (DEBUG) Log.d(TAG, "doKeyguard: not showing because lockscreen is off");
return;
}
-
- if (mLockPatternUtils.checkVoldPassword(KeyguardUpdateMonitor.getCurrentUser())) {
- if (DEBUG) Log.d(TAG, "Not showing lock screen since just decrypted");
- // Without this, settings is not enabled until the lock screen first appears
- setShowingLocked(false);
- hideLocked();
- return;
- }
}
if (DEBUG) Log.d(TAG, "doKeyguard: showing the lock screen");
@@ -2353,7 +2347,8 @@
// Hack level over 9000: To speed up wake-and-unlock sequence, force it to report
// the next draw from here, so we don't have to wait for window manager to signal
// this to our ViewRootImpl.
- mKeyguardViewControllerLazy.get().getViewRootImpl().setReportNextDraw();
+ mKeyguardViewControllerLazy.get().getViewRootImpl().setReportNextDraw(
+ false /* syncBuffer */);
mScreenOnCoordinator.setWakeAndUnlocking(false);
}
@@ -2813,6 +2808,7 @@
RemoteAnimationTarget[] apps, RemoteAnimationTarget[] wallpapers,
RemoteAnimationTarget[] nonApps, IRemoteAnimationFinishedCallback finishedCallback) {
Trace.beginSection("KeyguardViewMediator#startKeyguardExitAnimation");
+ mInteractionJankMonitor.cancel(CUJ_LOCKSCREEN_TRANSITION_FROM_AOD);
Message msg = mHandler.obtainMessage(START_KEYGUARD_EXIT_ANIM,
new StartKeyguardExitAnimParams(transit, startTime, fadeoutDuration, apps,
wallpapers, nonApps, finishedCallback));
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/WorkLockActivity.java b/packages/SystemUI/src/com/android/systemui/keyguard/WorkLockActivity.java
index b337183..e6b650b 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/WorkLockActivity.java
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/WorkLockActivity.java
@@ -94,7 +94,7 @@
// Blank out the activity. When it is on-screen it will look like a Recents thumbnail with
// redaction switched on.
final DevicePolicyManager dpm = getSystemService(DevicePolicyManager.class);
- String contentDescription = dpm.getString(
+ String contentDescription = dpm.getResources().getString(
WORK_LOCK_ACCESSIBILITY, () -> getString(R.string.accessibility_desc_work_lock));
final View blankView = new View(this);
blankView.setContentDescription(contentDescription);
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/dagger/KeyguardModule.java b/packages/SystemUI/src/com/android/systemui/keyguard/dagger/KeyguardModule.java
index c69f947..71dfa74 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/dagger/KeyguardModule.java
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/dagger/KeyguardModule.java
@@ -16,10 +16,8 @@
package com.android.systemui.keyguard.dagger;
-import android.annotation.Nullable;
import android.app.trust.TrustManager;
import android.content.Context;
-import android.content.pm.PackageManager;
import android.os.PowerManager;
import com.android.internal.jank.InteractionJankMonitor;
@@ -44,18 +42,14 @@
import com.android.systemui.keyguard.KeyguardUnlockAnimationController;
import com.android.systemui.keyguard.KeyguardViewMediator;
import com.android.systemui.navigationbar.NavigationModeController;
-import com.android.systemui.plugins.statusbar.StatusBarStateController;
import com.android.systemui.statusbar.NotificationShadeDepthController;
import com.android.systemui.statusbar.NotificationShadeWindowController;
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.KeyguardLiftController;
import com.android.systemui.statusbar.phone.ScreenOffAnimationController;
import com.android.systemui.statusbar.policy.KeyguardStateController;
import com.android.systemui.statusbar.policy.UserSwitcherController;
import com.android.systemui.util.DeviceConfigProxy;
-import com.android.systemui.util.sensors.AsyncSensorManager;
import java.util.concurrent.Executor;
@@ -133,20 +127,4 @@
notificationShadeWindowController,
activityLaunchAnimator);
}
-
- @SysUISingleton
- @Provides
- @Nullable
- static KeyguardLiftController provideKeyguardLiftController(
- Context context,
- StatusBarStateController statusBarStateController,
- AsyncSensorManager asyncSensorManager,
- KeyguardUpdateMonitor keyguardUpdateMonitor,
- DumpManager dumpManager) {
- if (!context.getPackageManager().hasSystemFeature(PackageManager.FEATURE_FACE)) {
- return null;
- }
- return new KeyguardLiftController(statusBarStateController, asyncSensorManager,
- keyguardUpdateMonitor, dumpManager);
- }
}
diff --git a/packages/SystemUI/src/com/android/systemui/media/MediaControlPanel.java b/packages/SystemUI/src/com/android/systemui/media/MediaControlPanel.java
index 510d15b..ffdd537 100644
--- a/packages/SystemUI/src/com/android/systemui/media/MediaControlPanel.java
+++ b/packages/SystemUI/src/com/android/systemui/media/MediaControlPanel.java
@@ -137,7 +137,6 @@
private MediaCarouselController mMediaCarouselController;
private final MediaOutputDialogFactory mMediaOutputDialogFactory;
private final FalsingManager mFalsingManager;
- private final MediaFlags mMediaFlags;
// Used for swipe-to-dismiss logging.
protected boolean mIsImpressed = false;
@@ -156,7 +155,7 @@
Lazy<MediaDataManager> lazyMediaDataManager,
MediaOutputDialogFactory mediaOutputDialogFactory,
MediaCarouselController mediaCarouselController,
- FalsingManager falsingManager, MediaFlags mediaFlags, SystemClock systemClock) {
+ FalsingManager falsingManager, SystemClock systemClock) {
mContext = context;
mBackgroundExecutor = backgroundExecutor;
mActivityStarter = activityStarter;
@@ -167,7 +166,6 @@
mMediaOutputDialogFactory = mediaOutputDialogFactory;
mMediaCarouselController = mediaCarouselController;
mFalsingManager = falsingManager;
- mMediaFlags = mediaFlags;
mSystemClock = systemClock;
loadDimens();
@@ -506,9 +504,8 @@
List<MediaAction> actionIcons = data.getActions();
List<Integer> actionsWhenCollapsed = data.getActionsToShowInCompact();
- // If the session actions flag is enabled, but we're still using the regular layout, use
- // the session actions anyways
- if (mMediaFlags.areMediaSessionActionsEnabled() && data.getSemanticActions() != null) {
+ // If we got session actions, use those instead
+ if (data.getSemanticActions() != null) {
MediaButton semanticActions = data.getSemanticActions();
actionIcons = new ArrayList<MediaAction>();
diff --git a/packages/SystemUI/src/com/android/systemui/media/MediaDataManager.kt b/packages/SystemUI/src/com/android/systemui/media/MediaDataManager.kt
index 9e14fe9..56d8c64 100644
--- a/packages/SystemUI/src/com/android/systemui/media/MediaDataManager.kt
+++ b/packages/SystemUI/src/com/android/systemui/media/MediaDataManager.kt
@@ -610,7 +610,8 @@
var actionIcons: List<MediaAction> = emptyList()
var actionsToShowCollapsed: List<Int> = emptyList()
var semanticActions: MediaButton? = null
- if (mediaFlags.areMediaSessionActionsEnabled() && mediaController.playbackState != null) {
+ if (mediaFlags.areMediaSessionActionsEnabled(sbn.packageName, sbn.user) &&
+ mediaController.playbackState != null) {
semanticActions = createActionsFromState(sbn.packageName, mediaController)
} else {
val actions = createActionsFromNotification(sbn)
@@ -726,7 +727,7 @@
}
}
- // Finally, assign the remaining button slots: C A play/pause B D
+ // Finally, assign the remaining button slots: play/pause A B C D
// A = previous, else custom action (if not reserved)
// B = next, else custom action (if not reserved)
// C and D are always custom actions
diff --git a/packages/SystemUI/src/com/android/systemui/media/MediaFlags.kt b/packages/SystemUI/src/com/android/systemui/media/MediaFlags.kt
index dd35a9a..59237d9 100644
--- a/packages/SystemUI/src/com/android/systemui/media/MediaFlags.kt
+++ b/packages/SystemUI/src/com/android/systemui/media/MediaFlags.kt
@@ -16,6 +16,8 @@
package com.android.systemui.media
+import android.app.StatusBarManager
+import android.os.UserHandle
import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.flags.FeatureFlags
import com.android.systemui.flags.Flags
@@ -26,16 +28,17 @@
/**
* Check whether media control actions should be based on PlaybackState instead of notification
*/
- fun areMediaSessionActionsEnabled(): Boolean {
- return featureFlags.isEnabled(Flags.MEDIA_SESSION_ACTIONS)
+ fun areMediaSessionActionsEnabled(packageName: String, user: UserHandle): Boolean {
+ val enabled = StatusBarManager.useMediaSessionActionsForApp(packageName, user)
+ // Allow global override with flag
+ return enabled || featureFlags.isEnabled(Flags.MEDIA_SESSION_ACTIONS)
}
/**
* Check whether media controls should use the new session-based layout
*/
fun useMediaSessionLayout(): Boolean {
- return featureFlags.isEnabled(Flags.MEDIA_SESSION_ACTIONS) &&
- featureFlags.isEnabled(Flags.MEDIA_SESSION_LAYOUT)
+ return featureFlags.isEnabled(Flags.MEDIA_SESSION_LAYOUT)
}
/**
diff --git a/packages/SystemUI/src/com/android/systemui/media/MediaHierarchyManager.kt b/packages/SystemUI/src/com/android/systemui/media/MediaHierarchyManager.kt
index 7a4dee2..d472aee 100644
--- a/packages/SystemUI/src/com/android/systemui/media/MediaHierarchyManager.kt
+++ b/packages/SystemUI/src/com/android/systemui/media/MediaHierarchyManager.kt
@@ -812,7 +812,7 @@
@TransformationType
fun calculateTransformationType(): Int {
if (isTransitioningToFullShade) {
- if (inSplitShade) {
+ if (inSplitShade && areGuidedTransitionHostsVisible()) {
return TRANSFORMATION_TYPE_TRANSITION
}
return TRANSFORMATION_TYPE_FADE
@@ -829,6 +829,11 @@
return TRANSFORMATION_TYPE_TRANSITION
}
+ private fun areGuidedTransitionHostsVisible(): Boolean {
+ return getHost(previousLocation)?.visible == true &&
+ getHost(desiredLocation)?.visible == true
+ }
+
/**
* @return the current transformation progress if we're in a guided transformation and -1
* otherwise
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 0b23ad5..a646482 100644
--- a/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputAdapter.java
+++ b/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputAdapter.java
@@ -119,7 +119,9 @@
mCheckBox.setVisibility(View.GONE);
mStatusIcon.setVisibility(View.GONE);
mContainerLayout.setOnClickListener(null);
- mTitleText.setTextColor(mController.getColorInactiveItem());
+ mTitleText.setTextColor(mController.getColorItemContent());
+ mSubTitleText.setTextColor(mController.getColorItemContent());
+ mTwoLineTitleText.setTextColor(mController.getColorItemContent());
mSeekBar.getProgressDrawable().setColorFilter(
new PorterDuffColorFilter(mController.getColorSeekbarProgress(),
PorterDuff.Mode.SRC_IN));
@@ -140,7 +142,7 @@
&& !mController.hasAdjustVolumeUserRestriction()) {
mProgressBar.getIndeterminateDrawable().setColorFilter(
new PorterDuffColorFilter(
- mController.getColorInactiveItem(),
+ mController.getColorItemContent(),
PorterDuff.Mode.SRC_IN));
setSingleLineLayout(getItemTitle(device), true /* bFocused */,
false /* showSeekBar*/,
@@ -155,7 +157,7 @@
mTitleIcon.setAlpha(DEVICE_CONNECTED_ALPHA);
mStatusIcon.setImageDrawable(
mContext.getDrawable(R.drawable.media_output_status_failed));
- mStatusIcon.setColorFilter(mController.getColorInactiveItem());
+ mStatusIcon.setColorFilter(mController.getColorItemContent());
setTwoLineLayout(device, false /* bFocused */,
false /* showSeekBar */, false /* showProgressBar */,
true /* showSubtitle */, true /* showStatus */);
@@ -163,7 +165,7 @@
mContainerLayout.setOnClickListener(v -> onItemClick(v, device));
} else if (mController.getSelectedMediaDevice().size() > 1
&& isDeviceIncluded(mController.getSelectedMediaDevice(), device)) {
- mTitleText.setTextColor(mController.getColorActiveItem());
+ mTitleText.setTextColor(mController.getColorItemContent());
setSingleLineLayout(getItemTitle(device), true /* bFocused */,
true /* showSeekBar */,
false /* showProgressBar */, false /* showStatus */);
@@ -173,13 +175,13 @@
mCheckBox.setOnCheckedChangeListener((buttonView, isChecked) -> {
onCheckBoxClicked(false, device);
});
- setCheckBoxColor(mCheckBox, mController.getColorActiveItem());
+ setCheckBoxColor(mCheckBox, mController.getColorItemContent());
initSeekbar(device);
} else if (!mController.hasAdjustVolumeUserRestriction() && currentlyConnected) {
mStatusIcon.setImageDrawable(
mContext.getDrawable(R.drawable.media_output_status_check));
- mStatusIcon.setColorFilter(mController.getColorActiveItem());
- mTitleText.setTextColor(mController.getColorActiveItem());
+ mStatusIcon.setColorFilter(mController.getColorItemContent());
+ mTitleText.setTextColor(mController.getColorItemContent());
setSingleLineLayout(getItemTitle(device), true /* bFocused */,
true /* showSeekBar */,
false /* showProgressBar */, true /* showStatus */);
@@ -192,7 +194,7 @@
mCheckBox.setOnCheckedChangeListener((buttonView, isChecked) -> {
onCheckBoxClicked(true, device);
});
- setCheckBoxColor(mCheckBox, mController.getColorInactiveItem());
+ setCheckBoxColor(mCheckBox, mController.getColorItemContent());
setSingleLineLayout(getItemTitle(device), false /* bFocused */,
false /* showSeekBar */,
false /* showProgressBar */, false /* showStatus */);
@@ -214,7 +216,7 @@
@Override
void onBind(int customizedItem, boolean topMargin, boolean bottomMargin) {
if (customizedItem == CUSTOMIZED_ITEM_PAIR_NEW) {
- mTitleText.setTextColor(mController.getColorInactiveItem());
+ mTitleText.setTextColor(mController.getColorItemContent());
mCheckBox.setVisibility(View.GONE);
setSingleLineLayout(mContext.getText(R.string.media_output_dialog_pairing_new),
false /* bFocused */);
diff --git a/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputBaseAdapter.java b/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputBaseAdapter.java
index 62d5c8e..df0c14b 100644
--- a/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputBaseAdapter.java
+++ b/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputBaseAdapter.java
@@ -170,14 +170,16 @@
void setSingleLineLayout(CharSequence title, boolean bFocused, boolean showSeekBar,
boolean showProgressBar, boolean showStatus) {
mTwoLineLayout.setVisibility(View.GONE);
+ boolean isActive = showSeekBar || showProgressBar;
final Drawable backgroundDrawable =
- showSeekBar || showProgressBar
+ isActive
? mContext.getDrawable(R.drawable.media_output_item_background_active)
.mutate() : mContext.getDrawable(
R.drawable.media_output_item_background)
.mutate();
backgroundDrawable.setColorFilter(new PorterDuffColorFilter(
- mController.getColorItemBackground(),
+ isActive ? mController.getColorConnectedItemBackground()
+ : mController.getColorItemBackground(),
PorterDuff.Mode.SRC_IN));
mItemLayout.setBackground(backgroundDrawable);
mProgressBar.setVisibility(showProgressBar ? View.VISIBLE : View.GONE);
@@ -366,7 +368,7 @@
.mutate();
drawable.setColorFilter(
new PorterDuffColorFilter(Utils.getColorStateListDefaultColor(mContext,
- R.color.media_dialog_active_item_main_content),
+ R.color.media_dialog_item_main_content),
PorterDuff.Mode.SRC_IN));
return drawable;
}
diff --git a/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputBaseDialog.java b/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputBaseDialog.java
index a8141c0..dcb1c7c 100644
--- a/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputBaseDialog.java
+++ b/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputBaseDialog.java
@@ -216,6 +216,7 @@
PorterDuff.Mode.SRC_IN);
mDoneButton.getBackground().setColorFilter(buttonColorFilter);
mStopButton.getBackground().setColorFilter(buttonColorFilter);
+ mDoneButton.setTextColor(mAdapter.getController().getColorPositiveButtonText());
}
mHeaderIcon.setVisibility(View.VISIBLE);
mHeaderIcon.setImageIcon(icon);
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 0b6c68d..ea7f7f2 100644
--- a/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputController.java
+++ b/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputController.java
@@ -110,11 +110,12 @@
private MediaOutputMetricLogger mMetricLogger;
- private int mColorActiveItem;
- private int mColorInactiveItem;
+ private int mColorItemContent;
private int mColorSeekbarProgress;
private int mColorButtonBackground;
private int mColorItemBackground;
+ private int mColorConnectedItemBackground;
+ private int mColorPositiveButtonText;
@Inject
public MediaOutputController(@NonNull Context context, String packageName,
@@ -133,16 +134,18 @@
mMetricLogger = new MediaOutputMetricLogger(mContext, mPackageName);
mDialogLaunchAnimator = dialogLaunchAnimator;
mNearbyMediaDevicesManager = nearbyMediaDevicesManagerOptional.orElse(null);
- mColorActiveItem = Utils.getColorStateListDefaultColor(mContext,
- R.color.media_dialog_active_item_main_content);
- mColorInactiveItem = Utils.getColorStateListDefaultColor(mContext,
- R.color.media_dialog_inactive_item_main_content);
+ mColorItemContent = Utils.getColorStateListDefaultColor(mContext,
+ R.color.media_dialog_item_main_content);
mColorSeekbarProgress = Utils.getColorStateListDefaultColor(mContext,
- android.R.color.system_accent1_200);
+ R.color.media_dialog_seekbar_progress);
mColorButtonBackground = Utils.getColorStateListDefaultColor(mContext,
- R.color.media_dialog_item_background);
+ R.color.media_dialog_button_background);
mColorItemBackground = Utils.getColorStateListDefaultColor(mContext,
- android.R.color.system_accent2_50);
+ R.color.media_dialog_item_background);
+ mColorConnectedItemBackground = Utils.getColorStateListDefaultColor(mContext,
+ R.color.media_dialog_connected_item_background);
+ mColorPositiveButtonText = Utils.getColorStateListDefaultColor(mContext,
+ R.color.media_dialog_solid_button_text);
}
void start(@NonNull Callback cb) {
@@ -322,8 +325,7 @@
}
void setColorFilter(Drawable drawable, boolean isActive) {
- drawable.setColorFilter(new PorterDuffColorFilter(isActive
- ? mColorActiveItem : mColorInactiveItem,
+ drawable.setColorFilter(new PorterDuffColorFilter(mColorItemContent,
PorterDuff.Mode.SRC_IN));
}
@@ -358,26 +360,32 @@
ColorScheme mCurrentColorScheme = new ColorScheme(wallpaperColors,
isDarkTheme);
if (isDarkTheme) {
- mColorActiveItem = mCurrentColorScheme.getNeutral1().get(10);
- mColorInactiveItem = mCurrentColorScheme.getNeutral1().get(10);
- mColorSeekbarProgress = mCurrentColorScheme.getAccent1().get(2);
- mColorButtonBackground = mCurrentColorScheme.getAccent1().get(2);
- mColorItemBackground = mCurrentColorScheme.getAccent2().get(0);
+ 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
} else {
- mColorActiveItem = mCurrentColorScheme.getNeutral1().get(10);
- mColorInactiveItem = mCurrentColorScheme.getAccent1().get(7);
- mColorSeekbarProgress = mCurrentColorScheme.getAccent1().get(3);
- mColorButtonBackground = mCurrentColorScheme.getAccent1().get(3);
- mColorItemBackground = mCurrentColorScheme.getAccent2().get(0);
+ 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
}
}
- public int getColorActiveItem() {
- return mColorActiveItem;
+ public int getColorConnectedItemBackground() {
+ return mColorConnectedItemBackground;
}
- public int getColorInactiveItem() {
- return mColorInactiveItem;
+ public int getColorPositiveButtonText() {
+ return mColorPositiveButtonText;
+ }
+
+ public int getColorItemContent() {
+ return mColorItemContent;
}
public int getColorSeekbarProgress() {
diff --git a/packages/SystemUI/src/com/android/systemui/media/taptotransfer/MediaTttCommandLineHelper.kt b/packages/SystemUI/src/com/android/systemui/media/taptotransfer/MediaTttCommandLineHelper.kt
index 3961f07..e4b8874 100644
--- a/packages/SystemUI/src/com/android/systemui/media/taptotransfer/MediaTttCommandLineHelper.kt
+++ b/packages/SystemUI/src/com/android/systemui/media/taptotransfer/MediaTttCommandLineHelper.kt
@@ -128,19 +128,21 @@
as StatusBarManager
val routeInfo = MediaRoute2Info.Builder("id", "Test Name")
.addFeature("feature")
- .setPackageName(TEST_PACKAGE_NAME)
- .build()
+ if (args.size >= 2 && args[1] == "useAppIcon=true") {
+ routeInfo.setPackageName(TEST_PACKAGE_NAME)
+ }
statusBarManager.updateMediaTapToTransferReceiverDisplay(
displayState,
- routeInfo,
+ routeInfo.build(),
null,
null
)
}
override fun help(pw: PrintWriter) {
- pw.println("Usage: adb shell cmd statusbar $RECEIVER_COMMAND <chipState>")
+ pw.println("Usage: adb shell cmd statusbar $RECEIVER_COMMAND " +
+ "<chipState> useAppIcon=[true|false]")
}
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/media/taptotransfer/common/MediaTttChipControllerCommon.kt b/packages/SystemUI/src/com/android/systemui/media/taptotransfer/common/MediaTttChipControllerCommon.kt
index 71cacac..54b0c13 100644
--- a/packages/SystemUI/src/com/android/systemui/media/taptotransfer/common/MediaTttChipControllerCommon.kt
+++ b/packages/SystemUI/src/com/android/systemui/media/taptotransfer/common/MediaTttChipControllerCommon.kt
@@ -31,7 +31,9 @@
import android.view.View
import android.view.ViewGroup
import android.view.WindowManager
+import android.widget.LinearLayout
import com.android.internal.widget.CachingIconView
+import com.android.settingslib.Utils
import com.android.systemui.R
import com.android.systemui.dagger.qualifiers.Main
import com.android.systemui.statusbar.gesture.TapGestureDetector
@@ -136,6 +138,11 @@
abstract fun updateChipView(chipInfo: T, currentChipView: ViewGroup)
/**
+ * Returns the size that the icon should be, or null if no size override is needed.
+ */
+ open fun getIconSize(isAppIcon: Boolean): Int? = null
+
+ /**
* An internal method to set the icon on the view.
*
* This is in the common superclass since both the sender and the receiver show an icon.
@@ -150,40 +157,48 @@
appNameOverride: CharSequence? = null,
) {
val appIconView = currentChipView.requireViewById<CachingIconView>(R.id.app_icon)
- appIconView.contentDescription = appNameOverride ?: getAppName(appPackageName)
+ val iconInfo = getIconInfo(appPackageName)
- val appIcon = appIconDrawableOverride ?: getAppIcon(appPackageName)
- val visibility = if (appIcon != null) {
- View.VISIBLE
- } else {
- View.GONE
+ getIconSize(iconInfo.isAppIcon)?.let { size ->
+ val lp = appIconView.layoutParams
+ lp.width = size
+ lp.height = size
+ appIconView.layoutParams = lp
}
- appIconView.setImageDrawable(appIcon)
- appIconView.visibility = visibility
+
+ appIconView.contentDescription = appNameOverride ?: iconInfo.iconName
+ appIconView.setImageDrawable(appIconDrawableOverride ?: iconInfo.icon)
}
- /** Returns the icon of the app playing the media or null if we can't find it. */
- private fun getAppIcon(appPackageName: String?): Drawable? {
- appPackageName ?: return null
- return try {
- context.packageManager.getApplicationIcon(appPackageName)
- } catch (e: PackageManager.NameNotFoundException) {
- Log.w(TAG, "Cannot find icon for package $appPackageName", e)
- null
+ /**
+ * Returns the information needed to display the icon.
+ *
+ * The information will either contain app name and icon of the app playing media, or a default
+ * name and icon if we can't find the app name/icon.
+ */
+ private fun getIconInfo(appPackageName: String?): IconInfo {
+ if (appPackageName != null) {
+ try {
+ return IconInfo(
+ iconName = context.packageManager.getApplicationInfo(
+ appPackageName, PackageManager.ApplicationInfoFlags.of(0)
+ ).loadLabel(context.packageManager).toString(),
+ icon = context.packageManager.getApplicationIcon(appPackageName),
+ isAppIcon = true
+ )
+ } catch (e: PackageManager.NameNotFoundException) {
+ Log.w(TAG, "Cannot find package $appPackageName", e)
+ }
}
- }
-
- /** Returns the name of the app playing the media or null if we can't find it. */
- private fun getAppName(appPackageName: String?): String? {
- appPackageName ?: return null
- return try {
- context.packageManager.getApplicationInfo(
- appPackageName, PackageManager.ApplicationInfoFlags.of(0)
- ).loadLabel(context.packageManager).toString()
- } catch (e: PackageManager.NameNotFoundException) {
- Log.w(TAG, "Cannot find name for package $appPackageName", e)
- null
- }
+ return IconInfo(
+ iconName = context.getString(R.string.media_output_dialog_unknown_launch_app_name),
+ icon = context.resources.getDrawable(R.drawable.ic_cast).apply {
+ this.setTint(
+ Utils.getColorAttrDefaultColor(context, android.R.attr.textColorPrimary)
+ )
+ },
+ isAppIcon = false
+ )
}
private fun onScreenTapped(e: MotionEvent) {
@@ -205,3 +220,10 @@
const val REASON_TIMEOUT = "TIMEOUT"
const val REASON_SCREEN_TAP = "SCREEN_TAP"
}
+
+private data class IconInfo(
+ val iconName: String,
+ val icon: Drawable,
+ /** True if [icon] is the app's icon, and false if [icon] is some generic default icon. */
+ val isAppIcon: Boolean
+)
diff --git a/packages/SystemUI/src/com/android/systemui/media/taptotransfer/receiver/MediaTttChipControllerReceiver.kt b/packages/SystemUI/src/com/android/systemui/media/taptotransfer/receiver/MediaTttChipControllerReceiver.kt
index 44965d7..072263f 100644
--- a/packages/SystemUI/src/com/android/systemui/media/taptotransfer/receiver/MediaTttChipControllerReceiver.kt
+++ b/packages/SystemUI/src/com/android/systemui/media/taptotransfer/receiver/MediaTttChipControllerReceiver.kt
@@ -127,6 +127,15 @@
chipInfo.appNameOverride
)
}
+
+ override fun getIconSize(isAppIcon: Boolean): Int? =
+ context.resources.getDimensionPixelSize(
+ if (isAppIcon) {
+ R.dimen.media_ttt_icon_size_receiver
+ } else {
+ R.dimen.media_ttt_generic_icon_size_receiver
+ }
+ )
}
data class ChipReceiverInfo(
diff --git a/packages/SystemUI/src/com/android/systemui/navigationbar/gestural/EdgeBackGestureHandler.java b/packages/SystemUI/src/com/android/systemui/navigationbar/gestural/EdgeBackGestureHandler.java
index 4dacf5d..001a462 100644
--- a/packages/SystemUI/src/com/android/systemui/navigationbar/gestural/EdgeBackGestureHandler.java
+++ b/packages/SystemUI/src/com/android/systemui/navigationbar/gestural/EdgeBackGestureHandler.java
@@ -57,6 +57,7 @@
import com.android.internal.config.sysui.SystemUiDeviceConfigFlags;
import com.android.internal.policy.GestureNavigationSettingsObserver;
+import com.android.internal.util.LatencyTracker;
import com.android.systemui.R;
import com.android.systemui.SystemUIFactory;
import com.android.systemui.broadcast.BroadcastDispatcher;
@@ -198,6 +199,7 @@
private final Rect mNavBarOverlayExcludedBounds = new Rect();
private final Region mExcludeRegion = new Region();
private final Region mUnrestrictedExcludeRegion = new Region();
+ private final LatencyTracker mLatencyTracker;
// The left side edge width where touch down is allowed
private int mEdgeWidthLeft;
@@ -302,7 +304,7 @@
BroadcastDispatcher broadcastDispatcher, ProtoTracer protoTracer,
NavigationModeController navigationModeController, ViewConfiguration viewConfiguration,
WindowManager windowManager, IWindowManager windowManagerService,
- FalsingManager falsingManager) {
+ FalsingManager falsingManager, LatencyTracker latencyTracker) {
super(broadcastDispatcher);
mContext = context;
mDisplayId = context.getDisplayId();
@@ -316,6 +318,7 @@
mWindowManager = windowManager;
mWindowManagerService = windowManagerService;
mFalsingManager = falsingManager;
+ mLatencyTracker = latencyTracker;
ComponentName recentsComponentName = ComponentName.unflattenFromString(
context.getString(com.android.internal.R.string.config_recentsComponentName));
if (recentsComponentName != null) {
@@ -505,7 +508,8 @@
Choreographer.getInstance(), this::onInputEvent);
// Add a nav bar panel window
- setEdgeBackPlugin(new NavigationBarEdgePanel(mContext, mBackAnimation));
+ setEdgeBackPlugin(
+ new NavigationBarEdgePanel(mContext, mBackAnimation, mLatencyTracker));
mPluginManager.addPluginListener(
this, NavigationEdgeBackPlugin.class, /*allowMultiple=*/ false);
}
@@ -520,7 +524,7 @@
@Override
public void onPluginDisconnected(NavigationEdgeBackPlugin plugin) {
- setEdgeBackPlugin(new NavigationBarEdgePanel(mContext, mBackAnimation));
+ setEdgeBackPlugin(new NavigationBarEdgePanel(mContext, mBackAnimation, mLatencyTracker));
}
private void setEdgeBackPlugin(NavigationEdgeBackPlugin edgeBackPlugin) {
@@ -968,6 +972,7 @@
private final WindowManager mWindowManager;
private final IWindowManager mWindowManagerService;
private final FalsingManager mFalsingManager;
+ private final LatencyTracker mLatencyTracker;
@Inject
public Factory(OverviewProxyService overviewProxyService,
@@ -975,7 +980,8 @@
BroadcastDispatcher broadcastDispatcher, ProtoTracer protoTracer,
NavigationModeController navigationModeController,
ViewConfiguration viewConfiguration, WindowManager windowManager,
- IWindowManager windowManagerService, FalsingManager falsingManager) {
+ IWindowManager windowManagerService, FalsingManager falsingManager,
+ LatencyTracker latencyTracker) {
mOverviewProxyService = overviewProxyService;
mSysUiState = sysUiState;
mPluginManager = pluginManager;
@@ -987,6 +993,7 @@
mWindowManager = windowManager;
mWindowManagerService = windowManagerService;
mFalsingManager = falsingManager;
+ mLatencyTracker = latencyTracker;
}
/** Construct a {@link EdgeBackGestureHandler}. */
@@ -994,7 +1001,7 @@
return new EdgeBackGestureHandler(context, mOverviewProxyService, mSysUiState,
mPluginManager, mExecutor, mBroadcastDispatcher, mProtoTracer,
mNavigationModeController, mViewConfiguration, mWindowManager,
- mWindowManagerService, mFalsingManager);
+ mWindowManagerService, mFalsingManager, mLatencyTracker);
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/navigationbar/gestural/NavigationBarEdgePanel.java b/packages/SystemUI/src/com/android/systemui/navigationbar/gestural/NavigationBarEdgePanel.java
index a6919e8..a1258df 100644
--- a/packages/SystemUI/src/com/android/systemui/navigationbar/gestural/NavigationBarEdgePanel.java
+++ b/packages/SystemUI/src/com/android/systemui/navigationbar/gestural/NavigationBarEdgePanel.java
@@ -51,6 +51,7 @@
import androidx.dynamicanimation.animation.SpringAnimation;
import androidx.dynamicanimation.animation.SpringForce;
+import com.android.internal.util.LatencyTracker;
import com.android.settingslib.Utils;
import com.android.systemui.Dependency;
import com.android.systemui.R;
@@ -176,6 +177,7 @@
private final ValueAnimator mArrowDisappearAnimation;
private final SpringForce mRegularTranslationSpring;
private final SpringForce mTriggerBackSpring;
+ private final LatencyTracker mLatencyTracker;
private VelocityTracker mVelocityTracker;
private boolean mIsDark = false;
@@ -225,6 +227,7 @@
private float mDisappearAmount;
private long mVibrationTime;
private int mScreenSize;
+ private boolean mTrackingBackArrowLatency = false;
private final Handler mHandler = new Handler();
private final Runnable mFailsafeRunnable = this::onFailsafe;
@@ -283,7 +286,7 @@
private BackAnimation mBackAnimation;
public NavigationBarEdgePanel(Context context,
- BackAnimation backAnimation) {
+ BackAnimation backAnimation, LatencyTracker latencyTracker) {
super(context);
mWindowManager = context.getSystemService(WindowManager.class);
@@ -383,6 +386,7 @@
}, backgroundExecutor);
mRegionSamplingHelper.setWindowVisible(true);
mShowProtection = !isPrimaryDisplay;
+ mLatencyTracker = latencyTracker;
}
public void setBackAnimation(BackAnimation backAnimation) {
@@ -492,6 +496,8 @@
updatePosition(event.getY());
mRegionSamplingHelper.start(mSamplingRect);
mWindowManager.updateViewLayout(this, mLayoutParams);
+ mLatencyTracker.onActionStart(LatencyTracker.ACTION_SHOW_BACK_ARROW);
+ mTrackingBackArrowLatency = true;
break;
case MotionEvent.ACTION_MOVE:
handleMoveEvent(event);
@@ -547,6 +553,10 @@
canvas.drawPath(arrowPath, mPaint);
canvas.restore();
+ if (mTrackingBackArrowLatency) {
+ mLatencyTracker.onActionEnd(LatencyTracker.ACTION_SHOW_BACK_ARROW);
+ mTrackingBackArrowLatency = false;
+ }
}
@Override
diff --git a/packages/SystemUI/src/com/android/systemui/privacy/PrivacyDialogController.kt b/packages/SystemUI/src/com/android/systemui/privacy/PrivacyDialogController.kt
index 6107123..8147877 100644
--- a/packages/SystemUI/src/com/android/systemui/privacy/PrivacyDialogController.kt
+++ b/packages/SystemUI/src/com/android/systemui/privacy/PrivacyDialogController.kt
@@ -150,24 +150,27 @@
packageName: String,
userId: Int,
permGroupName: CharSequence,
- attributionTag: CharSequence?
+ attributionTag: CharSequence?,
+ isAttributionSupported: Boolean
): Intent
{
lateinit var intent: Intent
- if (attributionTag != null) {
+ if (attributionTag != null && isAttributionSupported) {
intent = Intent(Intent.ACTION_MANAGE_PERMISSION_USAGE)
intent.setPackage(packageName)
intent.putExtra(Intent.EXTRA_PERMISSION_GROUP_NAME, permGroupName.toString())
intent.putExtra(Intent.EXTRA_ATTRIBUTION_TAGS, arrayOf(attributionTag.toString()))
intent.putExtra(Intent.EXTRA_SHOWING_ATTRIBUTION, true)
val resolveInfo = packageManager.resolveActivity(
- intent, PackageManager.ResolveInfoFlags.of(0))
- ?: return getDefaultManageAppPermissionsIntent(packageName, userId)
- intent.component = ComponentName(packageName, resolveInfo.activityInfo.name)
- return intent
- } else {
- return getDefaultManageAppPermissionsIntent(packageName, userId)
+ intent, PackageManager.ResolveInfoFlags.of(0))
+ if (resolveInfo != null && resolveInfo.activityInfo != null &&
+ resolveInfo.activityInfo.permission ==
+ android.Manifest.permission.START_VIEW_PERMISSION_USAGE) {
+ intent.component = ComponentName(packageName, resolveInfo.activityInfo.name)
+ return intent
+ }
}
+ return getDefaultManageAppPermissionsIntent(packageName, userId)
}
fun getDefaultManageAppPermissionsIntent(packageName: String, userId: Int): Intent {
@@ -226,9 +229,15 @@
userInfo?.isManagedProfile ?: false,
it.isPhoneCall,
it.permissionGroupName,
- getManagePermissionIntent(it.packageName, userId,
- it.permissionGroupName,
- it.attributionTag)
+ getManagePermissionIntent(
+ it.packageName,
+ userId,
+ it.permissionGroupName,
+ it.attributionTag,
+ // attributionLabel is set only when subattribution policies
+ // are supported and satisfied
+ it.attributionLabel != null
+ )
)
}
} else {
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSAnimator.java b/packages/SystemUI/src/com/android/systemui/qs/QSAnimator.java
index d1b569f..4640205 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSAnimator.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSAnimator.java
@@ -241,7 +241,13 @@
private void addNonFirstPageAnimators(int page) {
Pair<HeightExpansionAnimator, TouchAnimator> pair = createSecondaryPageAnimators(page);
- mNonFirstPageQSAnimators.put(page, pair);
+ if (pair != null) {
+ // pair is null in one of two cases:
+ // * mPagedTileLayout is null, meaning we are still setting up.
+ // * the page has no tiles
+ // In either case, don't add the animators to the map.
+ mNonFirstPageQSAnimators.put(page, pair);
+ }
}
@Override
@@ -518,6 +524,13 @@
SideLabelTileLayout qqsLayout = (SideLabelTileLayout) mQuickQsPanel.getTileLayout();
View view = mQs.getView();
List<String> specs = mPagedLayout.getSpecsForPage(page);
+ if (specs.isEmpty()) {
+ // specs should not be empty in a valid secondary page, as we scrolled to it.
+ // We may crash later on because there's a null animator.
+ specs = mQsPanelController.getHost().mTileSpecs;
+ Log.e(TAG, "Trying to create animators for empty page " + page + ". Tiles: " + specs);
+ // return null;
+ }
int row = -1;
int lastTileTop = -1;
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSSecurityFooter.java b/packages/SystemUI/src/com/android/systemui/qs/QSSecurityFooter.java
index 3824e1b..ea9bc69 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSSecurityFooter.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSSecurityFooter.java
@@ -325,12 +325,12 @@
private String getManagedDeviceMonitoringText(CharSequence organizationName) {
if (organizationName == null) {
- return mDpm.getString(
+ return mDpm.getResources().getString(
QS_MSG_MANAGEMENT_MONITORING,
() -> mContext.getString(
R.string.quick_settings_disclosure_management_monitoring));
}
- return mDpm.getString(
+ return mDpm.getResources().getString(
QS_MSG_NAMED_MANAGEMENT_MONITORING,
() -> mContext.getString(
R.string.quick_settings_disclosure_named_management_monitoring,
@@ -342,12 +342,12 @@
String vpnName, String vpnNameWorkProfile, CharSequence organizationName) {
if (vpnName != null && vpnNameWorkProfile != null) {
if (organizationName == null) {
- return mDpm.getString(
+ return mDpm.getResources().getString(
QS_MSG_MANAGEMENT_MULTIPLE_VPNS,
() -> mContext.getString(
R.string.quick_settings_disclosure_management_vpns));
}
- return mDpm.getString(
+ return mDpm.getResources().getString(
QS_MSG_NAMED_MANAGEMENT_MULTIPLE_VPNS,
() -> mContext.getString(
R.string.quick_settings_disclosure_named_management_vpns,
@@ -356,14 +356,14 @@
}
String name = vpnName != null ? vpnName : vpnNameWorkProfile;
if (organizationName == null) {
- return mDpm.getString(
+ return mDpm.getResources().getString(
QS_MSG_MANAGEMENT_NAMED_VPN,
() -> mContext.getString(
R.string.quick_settings_disclosure_management_named_vpn,
name),
name);
}
- return mDpm.getString(
+ return mDpm.getResources().getString(
QS_MSG_NAMED_MANAGEMENT_NAMED_VPN,
() -> mContext.getString(
R.string.quick_settings_disclosure_named_management_named_vpn,
@@ -375,7 +375,7 @@
private String getMangedDeviceGeneralText(CharSequence organizationName) {
if (organizationName == null) {
- return mDpm.getString(
+ return mDpm.getResources().getString(
QS_MSG_MANAGEMENT,
() -> mContext.getString(
R.string.quick_settings_disclosure_management));
@@ -385,7 +385,7 @@
R.string.quick_settings_financed_disclosure_named_management,
organizationName);
} else {
- return mDpm.getString(
+ return mDpm.getResources().getString(
QS_MSG_NAMED_MANAGEMENT,
() -> mContext.getString(
R.string.quick_settings_disclosure_named_management,
@@ -419,12 +419,12 @@
CharSequence workProfileOrganizationName, boolean isWorkProfileOn) {
if (hasCACertsInWorkProfile && isWorkProfileOn) {
if (workProfileOrganizationName == null) {
- return mDpm.getString(
+ return mDpm.getResources().getString(
QS_MSG_WORK_PROFILE_MONITORING,
() -> mContext.getString(
R.string.quick_settings_disclosure_managed_profile_monitoring));
}
- return mDpm.getString(
+ return mDpm.getResources().getString(
QS_MSG_NAMED_WORK_PROFILE_MONITORING,
() -> mContext.getString(
R.string.quick_settings_disclosure_named_managed_profile_monitoring,
@@ -443,7 +443,7 @@
return mContext.getString(R.string.quick_settings_disclosure_vpns);
}
if (vpnNameWorkProfile != null && isWorkProfileOn) {
- return mDpm.getString(
+ return mDpm.getResources().getString(
QS_MSG_WORK_PROFILE_NAMED_VPN,
() -> mContext.getString(
R.string.quick_settings_disclosure_managed_profile_named_vpn,
@@ -452,7 +452,7 @@
}
if (vpnName != null) {
if (hasWorkProfile) {
- return mDpm.getString(
+ return mDpm.getResources().getString(
QS_MSG_PERSONAL_PROFILE_NAMED_VPN,
() -> mContext.getString(
R.string.quick_settings_disclosure_personal_profile_named_vpn,
@@ -466,7 +466,7 @@
}
private String getManagedProfileNetworkActivityText() {
- return mDpm.getString(
+ return mDpm.getResources().getString(
QS_MSG_WORK_PROFILE_NETWORK,
() -> mContext.getString(
R.string.quick_settings_disclosure_managed_profile_network_activity));
@@ -634,7 +634,7 @@
@VisibleForTesting
String getSettingsButton() {
- return mDpm.getString(
+ return mDpm.getResources().getString(
QS_DIALOG_VIEW_POLICIES,
() -> mContext.getString(R.string.monitoring_button_view_policies));
}
@@ -662,7 +662,7 @@
return mContext.getString(R.string.monitoring_financed_description_named_management,
organizationName, organizationName);
} else {
- return mDpm.getString(
+ return mDpm.getResources().getString(
QS_DIALOG_NAMED_MANAGEMENT,
() -> mContext.getString(
R.string.monitoring_description_named_management,
@@ -670,7 +670,7 @@
organizationName);
}
}
- return mDpm.getString(
+ return mDpm.getResources().getString(
QS_DIALOG_MANAGEMENT,
() -> mContext.getString(R.string.monitoring_description_management));
}
@@ -680,13 +680,13 @@
boolean hasCACertsInWorkProfile) {
if (!(hasCACerts || hasCACertsInWorkProfile)) return null;
if (isDeviceManaged) {
- return mDpm.getString(
+ return mDpm.getResources().getString(
QS_DIALOG_MANAGEMENT_CA_CERT,
() -> mContext.getString(
R.string.monitoring_description_management_ca_certificate));
}
if (hasCACertsInWorkProfile) {
- return mDpm.getString(
+ return mDpm.getResources().getString(
QS_DIALOG_WORK_PROFILE_CA_CERT,
() -> mContext.getString(
R.string.monitoring_description_managed_profile_ca_certificate));
@@ -699,12 +699,12 @@
boolean isNetworkLoggingEnabled) {
if (!isNetworkLoggingEnabled) return null;
if (isDeviceManaged) {
- return mDpm.getString(
+ return mDpm.getResources().getString(
QS_DIALOG_MANAGEMENT_NETWORK,
() -> mContext.getString(
R.string.monitoring_description_management_network_logging));
} else {
- return mDpm.getString(
+ return mDpm.getResources().getString(
QS_DIALOG_WORK_PROFILE_NETWORK,
() -> mContext.getString(
R.string.monitoring_description_managed_profile_network_logging));
@@ -718,7 +718,7 @@
final SpannableStringBuilder message = new SpannableStringBuilder();
if (isDeviceManaged) {
if (vpnName != null && vpnNameWorkProfile != null) {
- String namedVpns = mDpm.getString(
+ String namedVpns = mDpm.getResources().getString(
QS_DIALOG_MANAGEMENT_TWO_NAMED_VPN,
() -> mContext.getString(
R.string.monitoring_description_two_named_vpns,
@@ -727,7 +727,7 @@
message.append(namedVpns);
} else {
String name = vpnName != null ? vpnName : vpnNameWorkProfile;
- String namedVp = mDpm.getString(
+ String namedVp = mDpm.getResources().getString(
QS_DIALOG_MANAGEMENT_NAMED_VPN,
() -> mContext.getString(R.string.monitoring_description_named_vpn, name),
name);
@@ -735,7 +735,7 @@
}
} else {
if (vpnName != null && vpnNameWorkProfile != null) {
- String namedVpns = mDpm.getString(
+ String namedVpns = mDpm.getResources().getString(
QS_DIALOG_MANAGEMENT_TWO_NAMED_VPN,
() -> mContext.getString(
R.string.monitoring_description_two_named_vpns,
@@ -743,7 +743,7 @@
vpnName, vpnNameWorkProfile);
message.append(namedVpns);
} else if (vpnNameWorkProfile != null) {
- String namedVpn = mDpm.getString(
+ String namedVpn = mDpm.getResources().getString(
QS_DIALOG_WORK_PROFILE_NAMED_VPN,
() -> mContext.getString(
R.string.monitoring_description_managed_profile_named_vpn,
@@ -751,7 +751,7 @@
vpnNameWorkProfile);
message.append(namedVpn);
} else if (hasWorkProfile) {
- String namedVpn = mDpm.getString(
+ String namedVpn = mDpm.getResources().getString(
QS_DIALOG_PERSONAL_PROFILE_NAMED_VPN,
() -> mContext.getString(
R.string.monitoring_description_personal_profile_named_vpn,
@@ -775,7 +775,7 @@
return mContext.getString(R.string.monitoring_title_financed_device,
deviceOwnerOrganization);
} else {
- return mDpm.getString(
+ return mDpm.getResources().getString(
QS_DIALOG_MANAGEMENT_TITLE,
() -> mContext.getString(R.string.monitoring_title_device_owned));
}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QuickStatusBarHeader.java b/packages/SystemUI/src/com/android/systemui/qs/QuickStatusBarHeader.java
index 8c08873..f2dd770 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QuickStatusBarHeader.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QuickStatusBarHeader.java
@@ -102,7 +102,7 @@
private int mTopViewMeasureHeight;
@NonNull
- private List<String> mRssiIgnoredSlots;
+ private List<String> mRssiIgnoredSlots = List.of();
private boolean mIsSingleCarrier;
private boolean mHasCenterCutout;
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/WorkModeTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/WorkModeTile.java
index 4279b62..7130294 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/WorkModeTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/WorkModeTile.java
@@ -104,7 +104,7 @@
@Override
public CharSequence getTileLabel() {
DevicePolicyManager dpm = mContext.getSystemService(DevicePolicyManager.class);
- return dpm.getString(QS_WORK_PROFILE_LABEL,
+ return dpm.getResources().getString(QS_WORK_PROFILE_LABEL,
() -> mContext.getString(R.string.quick_settings_work_mode_label));
}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/dialog/InternetAdapter.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/dialog/InternetAdapter.java
index 8bad2de..2cc3986 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/dialog/InternetAdapter.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/dialog/InternetAdapter.java
@@ -21,6 +21,7 @@
import android.graphics.drawable.Drawable;
import android.text.Html;
import android.text.TextUtils;
+import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
@@ -158,22 +159,47 @@
final int security = wifiEntry.getSecurity();
updateEndIcon(connectedState, security);
+ mWifiListLayout.setEnabled(shouldEnabled(wifiEntry));
if (connectedState != WifiEntry.CONNECTED_STATE_DISCONNECTED) {
mWifiListLayout.setOnClickListener(
- v -> mInternetDialogController.launchWifiNetworkDetailsSetting(
+ v -> mInternetDialogController.launchWifiDetailsSetting(
wifiEntry.getKey(), v));
return;
}
- mWifiListLayout.setOnClickListener(v -> {
- if (wifiEntry.shouldEditBeforeConnect()) {
- final Intent intent = WifiUtils.getWifiDialogIntent(wifiEntry.getKey(),
- true /* connectForCaller */);
- intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
- intent.addFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT);
- mContext.startActivity(intent);
- }
+ mWifiListLayout.setOnClickListener(v -> onWifiClick(wifiEntry, v));
+ }
+
+ boolean shouldEnabled(@NonNull WifiEntry wifiEntry) {
+ if (wifiEntry.canConnect()) {
+ return true;
+ }
+ // If Wi-Fi is connected or saved network, leave it enabled to disconnect or configure.
+ if (wifiEntry.canDisconnect() || wifiEntry.isSaved()) {
+ return true;
+ }
+ return false;
+ }
+
+ void onWifiClick(@NonNull WifiEntry wifiEntry, @NonNull View view) {
+ if (wifiEntry.shouldEditBeforeConnect()) {
+ final Intent intent = WifiUtils.getWifiDialogIntent(wifiEntry.getKey(),
+ true /* connectForCaller */);
+ intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+ intent.addFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT);
+ mContext.startActivity(intent);
+ return;
+ }
+
+ if (wifiEntry.canConnect()) {
mInternetDialogController.connect(wifiEntry);
- });
+ return;
+ }
+
+ if (wifiEntry.isSaved()) {
+ Log.w(TAG, "The saved Wi-Fi network does not allow to connect. SSID:"
+ + wifiEntry.getSsid());
+ mInternetDialogController.launchWifiDetailsSetting(wifiEntry.getKey(), view);
+ }
}
void setWifiNetworkLayout(CharSequence title, CharSequence summary) {
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/dialog/InternetDialog.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/dialog/InternetDialog.java
index d1c7844..8921e95 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/dialog/InternetDialog.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/dialog/InternetDialog.java
@@ -531,8 +531,7 @@
if (mConnectedWifiEntry == null) {
return;
}
- mInternetDialogController.launchWifiNetworkDetailsSetting(mConnectedWifiEntry.getKey(),
- view);
+ mInternetDialogController.launchWifiDetailsSetting(mConnectedWifiEntry.getKey(), view);
}
void onClickSeeMoreButton(View view) {
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/dialog/InternetDialogController.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/dialog/InternetDialogController.java
index b322cbf..d97ce77 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/dialog/InternetDialogController.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/dialog/InternetDialogController.java
@@ -635,7 +635,7 @@
startActivity(getSettingsIntent(), view);
}
- void launchWifiNetworkDetailsSetting(String key, View view) {
+ void launchWifiDetailsSetting(String key, View view) {
Intent intent = getWifiDetailsSettingsIntent(key);
if (intent != null) {
startActivity(intent, view);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardIndicationController.java b/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardIndicationController.java
index ccec0c2..d51aaad 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardIndicationController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardIndicationController.java
@@ -293,6 +293,14 @@
}
}
+ /**
+ * Cleanup
+ */
+ public void destroy() {
+ mHandler.removeCallbacksAndMessages(null);
+ mBroadcastDispatcher.unregisterReceiver(mBroadcastReceiver);
+ }
+
private void handleAlignStateChanged(int alignState) {
String alignmentIndication = "";
if (alignState == DockManager.ALIGN_STATE_POOR) {
@@ -374,7 +382,7 @@
private CharSequence getDisclosureText(@Nullable CharSequence organizationName) {
final Resources packageResources = mContext.getResources();
if (organizationName == null) {
- return mDevicePolicyManager.getString(
+ return mDevicePolicyManager.getResources().getString(
KEYGUARD_MANAGEMENT_DISCLOSURE,
() -> packageResources.getString(R.string.do_disclosure_generic));
} else if (mDevicePolicyManager.isDeviceManaged()
@@ -384,7 +392,7 @@
return packageResources.getString(R.string.do_financed_disclosure_with_name,
organizationName);
} else {
- return mDevicePolicyManager.getString(
+ return mDevicePolicyManager.getResources().getString(
KEYGUARD_MANAGEMENT_DISCLOSURE,
() -> packageResources.getString(
R.string.do_disclosure_with_name, organizationName),
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/LockscreenShadeTransitionController.kt b/packages/SystemUI/src/com/android/systemui/statusbar/LockscreenShadeTransitionController.kt
index ab4d0dd..de3e89d 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/LockscreenShadeTransitionController.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/LockscreenShadeTransitionController.kt
@@ -116,6 +116,16 @@
private var scrimTransitionDistance = 0
/**
+ * Distance that it takes in order for the notifications scrim fade in to start.
+ */
+ private var notificationsScrimTransitionDelay = 0
+
+ /**
+ * Distance that it takes for the notifications scrim to fully fade if after it started.
+ */
+ private var notificationsScrimTransitionDistance = 0
+
+ /**
* Distance that the full shade transition takes in order for the notification shelf to fully
* expand.
*/
@@ -225,6 +235,10 @@
R.dimen.lockscreen_shade_transition_by_tap_distance)
scrimTransitionDistance = context.resources.getDimensionPixelSize(
R.dimen.lockscreen_shade_scrim_transition_distance)
+ notificationsScrimTransitionDelay = context.resources.getDimensionPixelSize(
+ R.dimen.lockscreen_shade_notifications_scrim_transition_delay)
+ notificationsScrimTransitionDistance = context.resources.getDimensionPixelSize(
+ R.dimen.lockscreen_shade_notifications_scrim_transition_distance)
notificationShelfTransitionDistance = context.resources.getDimensionPixelSize(
R.dimen.lockscreen_shade_notif_shelf_transition_distance)
qsTransitionDistance = context.resources.getDimensionPixelSize(
@@ -405,6 +419,7 @@
false /* animate */, 0 /* delay */)
mediaHierarchyManager.setTransitionToFullShadeAmount(field)
+ transitionToShadeAmountScrim(field)
transitionToShadeAmountCommon(field)
transitionToShadeAmountKeyguard(field)
}
@@ -417,10 +432,15 @@
var qSDragProgress = 0f
private set
- private fun transitionToShadeAmountCommon(dragDownAmount: Float) {
+ private fun transitionToShadeAmountScrim(dragDownAmount: Float) {
val scrimProgress = MathUtils.saturate(dragDownAmount / scrimTransitionDistance)
- scrimController.setTransitionToFullShadeProgress(scrimProgress)
+ val notificationsScrimDragAmount = dragDownAmount - notificationsScrimTransitionDelay
+ val notificationsScrimProgress = MathUtils.saturate(
+ notificationsScrimDragAmount / notificationsScrimTransitionDistance)
+ scrimController.setTransitionToFullShadeProgress(scrimProgress, notificationsScrimProgress)
+ }
+ private fun transitionToShadeAmountCommon(dragDownAmount: Float) {
if (depthControllerTransitionDistance > 0) {
val depthProgress =
MathUtils.saturate(dragDownAmount / depthControllerTransitionDistance)
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationRemoteInputManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationRemoteInputManager.java
index 94a6d3e..66c1d87 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationRemoteInputManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationRemoteInputManager.java
@@ -507,12 +507,11 @@
Math.max(cx + cy, cx + (h - cy)),
Math.max((w - cx) + cy, (w - cx) + (h - cy)));
- riv.setRevealParameters(cx, cy, r);
- riv.setPendingIntent(pendingIntent);
+ riv.getController().setRevealParams(new RemoteInputView.RevealParams(cx, cy, r));
riv.getController().setPendingIntent(pendingIntent);
- riv.setRemoteInput(inputs, input, editedSuggestionInfo);
riv.getController().setRemoteInput(input);
riv.getController().setRemoteInputs(inputs);
+ riv.getController().setEditedSuggestionInfo(editedSuggestionInfo);
riv.focusAnimated();
if (userMessageContent != null) {
riv.setEditTextContent(userMessageContent);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShelf.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShelf.java
index 3dd717d..eaa66bb 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShelf.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShelf.java
@@ -226,10 +226,7 @@
? MathUtils.lerp(shortestWidth, getWidth(), fractionToShade)
: getWidth();
ActivatableNotificationView anv = (ActivatableNotificationView) this;
- NotificationBackgroundView bg = anv.getBackgroundNormal();
- if (bg != null) {
- anv.getBackgroundNormal().setActualWidth((int) actualWidth);
- }
+ anv.setBackgroundWidth((int) actualWidth);
if (mShelfIcons != null) {
mShelfIcons.setActualLayoutWidth((int) actualWidth);
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarMobileView.java b/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarMobileView.java
index 465ab93..3013ad0 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarMobileView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarMobileView.java
@@ -188,7 +188,7 @@
setContentDescription(state.contentDescription);
int newVisibility = state.visible && !mForceHidden ? View.VISIBLE : View.GONE;
- if (newVisibility != mMobileGroup.getVisibility()) {
+ if (newVisibility != mMobileGroup.getVisibility() && STATE_ICON == mVisibleState) {
mMobileGroup.setVisibility(newVisibility);
needsLayout = true;
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/events/SystemEventChipAnimationController.kt b/packages/SystemUI/src/com/android/systemui/statusbar/events/SystemEventChipAnimationController.kt
index 9795dcf..b74140d 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/events/SystemEventChipAnimationController.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/events/SystemEventChipAnimationController.kt
@@ -16,9 +16,12 @@
package com.android.systemui.statusbar.events
+import android.animation.Animator
+import android.animation.AnimatorListenerAdapter
+import android.animation.AnimatorSet
import android.animation.ValueAnimator
import android.content.Context
-import android.graphics.Point
+import android.graphics.Rect
import android.view.Gravity
import android.view.LayoutInflater
import android.view.View
@@ -30,6 +33,7 @@
import com.android.systemui.statusbar.phone.StatusBarContentInsetsProvider
import com.android.systemui.statusbar.window.StatusBarWindowController
import javax.inject.Inject
+import kotlin.math.roundToInt
/**
* Controls the view for system event animations.
@@ -38,7 +42,7 @@
private val context: Context,
private val statusBarWindowController: StatusBarWindowController,
private val contentInsetsProvider: StatusBarContentInsetsProvider
-) : SystemStatusChipAnimationCallback {
+) : SystemStatusAnimationCallback {
private lateinit var animationWindowView: FrameLayout
@@ -49,90 +53,169 @@
private var chipRight = 0
private var chipLeft = 0
private var chipWidth = 0
- private var dotCenter = Point(0, 0)
+ private var chipMinWidth = context.resources.getDimensionPixelSize(
+ R.dimen.ongoing_appops_chip_min_animation_width)
private var dotSize = context.resources.getDimensionPixelSize(
R.dimen.ongoing_appops_dot_diameter)
- // If the chip animates away to a persistent dot, then we modify the CHIP_OUT animation
- private var isAnimatingToDot = false
+ // Use during animation so that multiple animators can update the drawing rect
+ private var animRect = Rect()
// TODO: move to dagger
private var initialized = false
- override fun onChipAnimationStart(
- viewCreator: ViewCreator,
- @SystemAnimationState state: Int
- ) {
- if (!initialized) init()
+ /**
+ * Give the chip controller a chance to inflate and configure the chip view before we start
+ * animating
+ */
+ fun prepareChipAnimation(viewCreator: ViewCreator) {
+ if (!initialized) {
+ init()
+ }
+ animationDirection = if (animationWindowView.isLayoutRtl) RIGHT else LEFT
- if (state == ANIMATING_IN) {
- animationDirection = if (animationWindowView.isLayoutRtl) RIGHT else LEFT
+ // Initialize the animated view
+ val insets = contentInsetsProvider.getStatusBarContentInsetsForCurrentRotation()
+ currentAnimatedView = viewCreator(context).also {
+ animationWindowView.addView(
+ it.view,
+ layoutParamsDefault(
+ if (animationWindowView.isLayoutRtl) insets.first
+ else insets.second))
+ it.view.alpha = 0f
+ // For some reason, the window view's measured width is always 0 here, so use the
+ // parent (status bar)
+ it.view.measure(
+ View.MeasureSpec.makeMeasureSpec(
+ (animationWindowView.parent as View).width, AT_MOST),
+ View.MeasureSpec.makeMeasureSpec(animationWindowView.height, AT_MOST))
+ chipWidth = it.chipWidth
+ }
- // Initialize the animated view
- val insets = contentInsetsProvider.getStatusBarContentInsetsForCurrentRotation()
- currentAnimatedView = viewCreator(context).also {
- animationWindowView.addView(
- it.view,
- layoutParamsDefault(
- if (animationWindowView.isLayoutRtl) insets.first
- else insets.second))
- it.view.alpha = 0f
- // For some reason, the window view's measured width is always 0 here, so use the
- // parent (status bar)
- it.view.measure(
- View.MeasureSpec.makeMeasureSpec(
- (animationWindowView.parent as View).width, AT_MOST),
- View.MeasureSpec.makeMeasureSpec(animationWindowView.height, AT_MOST))
- chipWidth = it.chipWidth
+ // decide which direction we're animating from, and then set some screen coordinates
+ val contentRect = contentInsetsProvider.getStatusBarContentAreaForCurrentRotation()
+ when (animationDirection) {
+ LEFT -> {
+ chipRight = contentRect.right
+ chipLeft = contentRect.right - chipWidth
}
-
- // decide which direction we're animating from, and then set some screen coordinates
- val contentRect = contentInsetsProvider.getStatusBarContentAreaForCurrentRotation()
- when (animationDirection) {
- LEFT -> {
- chipRight = contentRect.right
- chipLeft = contentRect.right - chipWidth
- }
- else /* RIGHT */ -> {
- chipLeft = contentRect.left
- chipRight = contentRect.left + chipWidth
- }
- }
-
- currentAnimatedView?.apply {
- updateAnimatedViewBoundsForAmount(0.1f, this)
- }
- } else {
- // We are animating away
- currentAnimatedView!!.view.apply {
- alpha = 1f
+ else /* RIGHT */ -> {
+ chipLeft = contentRect.left
+ chipRight = contentRect.left + chipWidth
}
}
}
- override fun onChipAnimationEnd(@SystemAnimationState state: Int) {
- if (state == ANIMATING_IN) {
- // Finished animating in
- currentAnimatedView?.apply {
- updateAnimatedViewBoundsForAmount(1f, this)
- }
- } else {
- // Finished animating away
- currentAnimatedView!!.view.apply {
- visibility = View.INVISIBLE
- }
- animationWindowView.removeView(currentAnimatedView!!.view)
+ override fun onSystemEventAnimationBegin(): Animator {
+ initializeAnimRect()
+
+ val alphaIn = ValueAnimator.ofFloat(0f, 1f).apply {
+ startDelay = 117
+ duration = 83
+ interpolator = null
+ addUpdateListener { currentAnimatedView?.view?.alpha = animatedValue as Float }
}
+ val moveIn = ValueAnimator.ofInt(chipMinWidth, chipWidth).apply {
+ startDelay = 117
+ duration = 383
+ interpolator = STATUS_BAR_X_MOVE_IN
+ addUpdateListener {
+ updateAnimatedViewBoundsWidth(animatedValue as Int)
+ }
+ }
+ val animSet = AnimatorSet()
+ animSet.playTogether(alphaIn, moveIn)
+ return animSet
}
- override fun onChipAnimationUpdate(
- animator: ValueAnimator,
- @SystemAnimationState state: Int
- ) {
- currentAnimatedView?.apply {
- val amt = (animator.animatedValue as Float).amt()
- view.alpha = (animator.animatedValue as Float)
- updateAnimatedViewBoundsForAmount(amt, this)
+ override fun onSystemEventAnimationFinish(hasPersistentDot: Boolean): Animator {
+ initializeAnimRect()
+ val finish = if (hasPersistentDot) {
+ createMoveOutAnimationForDot()
+ } else {
+ createMoveOutAnimationDefault()
}
+
+ finish.addListener(object : AnimatorListenerAdapter() {
+ override fun onAnimationEnd(animation: Animator?) {
+ animationWindowView.removeView(currentAnimatedView!!.view)
+ }
+ })
+
+ return finish
+ }
+
+ private fun createMoveOutAnimationForDot(): Animator {
+ val width1 = ValueAnimator.ofInt(chipWidth, chipMinWidth).apply {
+ duration = 150
+ interpolator = STATUS_CHIP_WIDTH_TO_DOT_KEYFRAME_1
+ addUpdateListener {
+ updateAnimatedViewBoundsWidth(it.animatedValue as Int)
+ }
+ }
+
+ val width2 = ValueAnimator.ofInt(chipMinWidth, dotSize).apply {
+ startDelay = 150
+ duration = 333
+ interpolator = STATUS_CHIP_WIDTH_TO_DOT_KEYFRAME_2
+ addUpdateListener {
+ updateAnimatedViewBoundsWidth(it.animatedValue as Int)
+ }
+ }
+
+ val keyFrame1Height = dotSize * 2
+ val v = currentAnimatedView!!.view
+ val chipVerticalCenter = v.top + v.measuredHeight / 2
+ val height1 = ValueAnimator.ofInt(
+ currentAnimatedView!!.view.measuredHeight, keyFrame1Height).apply {
+ startDelay = 133
+ duration = 100
+ interpolator = STATUS_CHIP_HEIGHT_TO_DOT_KEYFRAME_1
+ addUpdateListener {
+ updateAnimatedViewBoundsHeight(it.animatedValue as Int, chipVerticalCenter)
+ }
+ }
+
+ val height2 = ValueAnimator.ofInt(keyFrame1Height, dotSize).apply {
+ startDelay = 233
+ duration = 250
+ interpolator = STATUS_CHIP_HEIGHT_TO_DOT_KEYFRAME_2
+ addUpdateListener {
+ updateAnimatedViewBoundsHeight(it.animatedValue as Int, chipVerticalCenter)
+ }
+ }
+
+ // Move the chip view to overlap exactly with the privacy dot. The chip displays by default
+ // exactly adjacent to the dot, so we can just move over by the diameter of the dot itself
+ val moveOut = ValueAnimator.ofInt(0, dotSize).apply {
+ startDelay = 50
+ duration = 183
+ interpolator = STATUS_CHIP_MOVE_TO_DOT
+ addUpdateListener {
+ // If RTL, we can just invert the move
+ val amt = if (animationDirection == LEFT) {
+ animatedValue as Int
+ } else {
+ -(animatedValue as Int)
+ }
+ updateAnimatedBoundsX(amt)
+ }
+ }
+
+ val animSet = AnimatorSet()
+ animSet.playTogether(width1, width2, height1, height2, moveOut)
+ return animSet
+ }
+
+ private fun createMoveOutAnimationDefault(): Animator {
+ val moveOut = ValueAnimator.ofInt(chipWidth, chipMinWidth).apply {
+ duration = 383
+ addUpdateListener {
+ currentAnimatedView?.apply {
+ updateAnimatedViewBoundsWidth(it.animatedValue as Int)
+ }
+ }
+ }
+ return moveOut
}
private fun init() {
@@ -144,7 +227,6 @@
statusBarWindowController.addViewToWindow(animationWindowView, lp)
animationWindowView.clipToPadding = false
animationWindowView.clipChildren = false
- animationWindowView.measureAllChildren = true
}
private fun layoutParamsDefault(marginEnd: Int): FrameLayout.LayoutParams =
@@ -153,29 +235,55 @@
it.marginEnd = marginEnd
}
- private fun updateAnimatedViewBoundsForAmount(amt: Float, chip: BackgroundAnimatableView) {
+ private fun initializeAnimRect() = animRect.set(
+ chipLeft,
+ currentAnimatedView!!.view.top,
+ chipRight,
+ currentAnimatedView!!.view.bottom)
+
+ /**
+ * To be called during an animation, sets the width and updates the current animated chip view
+ */
+ private fun updateAnimatedViewBoundsWidth(width: Int) {
when (animationDirection) {
LEFT -> {
- chip.setBoundsForAnimation(
- (chipRight - (chipWidth * amt)).toInt(),
- chip.view.top,
- chipRight,
- chip.view.bottom)
- }
- else /* RIGHT */ -> {
- chip.setBoundsForAnimation(
- chipLeft,
- chip.view.top,
- (chipLeft + (chipWidth * amt)).toInt(),
- chip.view.bottom)
+ animRect.set((chipRight - width), animRect.top, chipRight, animRect.bottom)
+ } else /* RIGHT */ -> {
+ animRect.set(chipLeft, animRect.top, (chipLeft + width), animRect.bottom)
}
}
+
+ updateCurrentAnimatedView()
}
- private fun start() = if (animationWindowView.isLayoutRtl) right() else left()
- private fun right() = contentInsetsProvider.getStatusBarContentAreaForCurrentRotation().right
- private fun left() = contentInsetsProvider.getStatusBarContentAreaForCurrentRotation().left
- private fun Float.amt() = 0.01f.coerceAtLeast(this)
+ /**
+ * To be called during an animation, updates the animation rect and sends the update to the chip
+ */
+ private fun updateAnimatedViewBoundsHeight(height: Int, verticalCenter: Int) {
+ animRect.set(
+ animRect.left,
+ verticalCenter - (height.toFloat() / 2).roundToInt(),
+ animRect.right,
+ verticalCenter + (height.toFloat() / 2).roundToInt())
+
+ updateCurrentAnimatedView()
+ }
+
+ /**
+ * To be called during an animation, updates the animation rect offset and updates the chip
+ */
+ private fun updateAnimatedBoundsX(translation: Int) {
+ currentAnimatedView?.view?.translationX = translation.toFloat()
+ }
+
+ /**
+ * To be called during an animation. Sets the chip rect to animRect
+ */
+ private fun updateCurrentAnimatedView() {
+ currentAnimatedView?.setBoundsForAnimation(
+ animRect.left, animRect.top, animRect.right, animRect.bottom
+ )
+ }
}
/**
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/events/SystemStatusAnimationScheduler.kt b/packages/SystemUI/src/com/android/systemui/statusbar/events/SystemStatusAnimationScheduler.kt
index 947f3eb..36233e4 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/events/SystemStatusAnimationScheduler.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/events/SystemStatusAnimationScheduler.kt
@@ -19,14 +19,12 @@
import android.animation.Animator
import android.animation.AnimatorListenerAdapter
import android.animation.AnimatorSet
-import android.animation.ValueAnimator
import android.annotation.IntDef
import android.os.Process
import android.provider.DeviceConfig
import android.util.Log
+import android.view.animation.PathInterpolator
import com.android.systemui.Dumpable
-import com.android.systemui.animation.Interpolators.STANDARD_ACCELERATE
-import com.android.systemui.animation.Interpolators.STANDARD_DECELERATE
import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.dagger.qualifiers.Main
@@ -38,6 +36,7 @@
import com.android.systemui.util.time.SystemClock
import java.io.FileDescriptor
import java.io.PrintWriter
+import java.lang.IllegalStateException
import javax.inject.Inject
@@ -116,7 +115,10 @@
scheduledEvent?.updateFromEvent(event)
if (event.forceVisible) {
hasPersistentDot = true
- notifyTransitionToPersistentDot()
+ // If we missed the chance to show the persistent dot, do it now
+ if (animationState == IDLE) {
+ notifyTransitionToPersistentDot()
+ }
}
} else {
if (DEBUG) {
@@ -162,68 +164,90 @@
return
}
- // Schedule the animation to start after a debounce period
- cancelExecutionRunnable = executor.executeDelayed({
- cancelExecutionRunnable = null
- animationState = ANIMATING_IN
- statusBarWindowController.setForceStatusBarVisible(true)
+ chipAnimationController.prepareChipAnimation(scheduledEvent!!.viewCreator)
+ animationState = ANIMATION_QUEUED
+ executor.executeDelayed({
+ runChipAnimation()
+ }, DEBOUNCE_DELAY)
+ }
- val entranceAnimator = ValueAnimator.ofFloat(1f, 0f)
- entranceAnimator.duration = ENTRANCE_ANIM_LENGTH
- entranceAnimator.addListener(systemAnimatorAdapter)
- entranceAnimator.addUpdateListener(systemUpdateListener)
- entranceAnimator.interpolator = STANDARD_ACCELERATE
+ /**
+ * 1. Define a total budget for the chip animation (1500ms)
+ * 2. Send out callbacks to listeners so that they can generate animations locally
+ * 3. Update the scheduler state so that clients know where we are
+ * 4. Maybe: provide scaffolding such as: dot location, margins, etc
+ * 5. Maybe: define a maximum animation length and enforce it. Probably only doable if we
+ * collect all of the animators and run them together.
+ */
+ private fun runChipAnimation() {
+ statusBarWindowController.setForceStatusBarVisible(true)
+ animationState = ANIMATING_IN
- val chipAnimator = ValueAnimator.ofFloat(0f, 1f)
- chipAnimator.duration = CHIP_ANIM_LENGTH
- chipAnimator.addListener(
- ChipAnimatorAdapter(RUNNING_CHIP_ANIM, scheduledEvent!!.viewCreator))
- chipAnimator.addUpdateListener(chipUpdateListener)
- chipAnimator.interpolator = STANDARD_DECELERATE
+ val animSet = collectStartAnimations()
+ if (animSet.totalDuration > 500) {
+ throw IllegalStateException("System animation total length exceeds budget. " +
+ "Expected: 500, actual: ${animSet.totalDuration}")
+ }
+ animSet.addListener(object : AnimatorListenerAdapter() {
+ override fun onAnimationEnd(animation: Animator?) {
+ animationState = RUNNING_CHIP_ANIM
+ }
+ })
+ animSet.start()
- val aSet2 = AnimatorSet()
- aSet2.playSequentially(entranceAnimator, chipAnimator)
- aSet2.start()
-
- executor.executeDelayed({
- animationState = ANIMATING_OUT
-
- val systemAnimator = ValueAnimator.ofFloat(0f, 1f)
- systemAnimator.duration = ENTRANCE_ANIM_LENGTH
- systemAnimator.addListener(systemAnimatorAdapter)
- systemAnimator.addUpdateListener(systemUpdateListener)
- systemAnimator.interpolator = STANDARD_DECELERATE
- systemAnimator.addListener(object : AnimatorListenerAdapter() {
- override fun onAnimationEnd(animation: Animator?) {
- statusBarWindowController.setForceStatusBarVisible(false)
+ executor.executeDelayed({
+ val animSet2 = collectFinishAnimations()
+ animationState = ANIMATING_OUT
+ animSet2.addListener(object : AnimatorListenerAdapter() {
+ override fun onAnimationEnd(animation: Animator?) {
+ animationState = if (hasPersistentDot) {
+ SHOWING_PERSISTENT_DOT
+ } else {
+ IDLE
}
- })
- val chipAnimator = ValueAnimator.ofFloat(1f, 0f)
- chipAnimator.duration = CHIP_ANIM_LENGTH
- val endState = if (hasPersistentDot) {
- SHOWING_PERSISTENT_DOT
- } else {
- IDLE
+ statusBarWindowController.setForceStatusBarVisible(false)
}
- chipAnimator.addListener(
- ChipAnimatorAdapter(endState, scheduledEvent!!.viewCreator))
- chipAnimator.addUpdateListener(chipUpdateListener)
- chipAnimator.interpolator = STANDARD_ACCELERATE
+ })
+ animSet2.start()
+ scheduledEvent = null
+ }, DISPLAY_LENGTH)
+ }
- val aSet2 = AnimatorSet()
+ private fun collectStartAnimations(): AnimatorSet {
+ val animators = mutableListOf<Animator>()
+ listeners.forEach { listener ->
+ listener.onSystemEventAnimationBegin()?.let { anim ->
+ animators.add(anim)
+ }
+ }
+ animators.add(chipAnimationController.onSystemEventAnimationBegin())
+ val animSet = AnimatorSet().also {
+ it.playTogether(animators)
+ }
- aSet2.play(chipAnimator).before(systemAnimator)
- if (hasPersistentDot) {
- val dotAnim = notifyTransitionToPersistentDot()
- if (dotAnim != null) aSet2.playTogether(systemAnimator, dotAnim)
- }
+ return animSet
+ }
- aSet2.start()
+ private fun collectFinishAnimations(): AnimatorSet {
+ val animators = mutableListOf<Animator>()
+ listeners.forEach { listener ->
+ listener.onSystemEventAnimationFinish(hasPersistentDot)?.let { anim ->
+ animators.add(anim)
+ }
+ }
+ animators.add(chipAnimationController.onSystemEventAnimationFinish(hasPersistentDot))
+ if (hasPersistentDot) {
+ val dotAnim = notifyTransitionToPersistentDot()
+ if (dotAnim != null) {
+ animators.add(dotAnim)
+ }
+ }
+ val animSet = AnimatorSet().also {
+ it.playTogether(animators)
+ }
- scheduledEvent = null
- }, DISPLAY_LENGTH)
- }, DELAY)
+ return animSet
}
private fun notifyTransitionToPersistentDot(): Animator? {
@@ -257,18 +281,6 @@
return null
}
- private fun notifySystemStart() {
- listeners.forEach { it.onSystemChromeAnimationStart() }
- }
-
- private fun notifySystemFinish() {
- listeners.forEach { it.onSystemChromeAnimationEnd() }
- }
-
- private fun notifySystemAnimationUpdate(anim: ValueAnimator) {
- listeners.forEach { it.onSystemChromeAnimationUpdate(anim) }
- }
-
override fun addCallback(listener: SystemStatusAnimationCallback) {
Assert.isMainThread()
@@ -287,24 +299,6 @@
}
}
- private val systemUpdateListener = ValueAnimator.AnimatorUpdateListener {
- anim -> notifySystemAnimationUpdate(anim)
- }
-
- private val systemAnimatorAdapter = object : AnimatorListenerAdapter() {
- override fun onAnimationEnd(p0: Animator?) {
- notifySystemFinish()
- }
-
- override fun onAnimationStart(p0: Animator?) {
- notifySystemStart()
- }
- }
-
- private val chipUpdateListener = ValueAnimator.AnimatorUpdateListener {
- anim -> chipAnimationController.onChipAnimationUpdate(anim, animationState)
- }
-
override fun dump(fd: FileDescriptor, pw: PrintWriter, args: Array<out String>) {
pw.println("Scheduled event: $scheduledEvent")
pw.println("Has persistent privacy dot: $hasPersistentDot")
@@ -318,24 +312,6 @@
}
}
}
-
- inner class ChipAnimatorAdapter(
- @SystemAnimationState val endState: Int,
- val viewCreator: ViewCreator
- ) : AnimatorListenerAdapter() {
- override fun onAnimationEnd(p0: Animator?) {
- chipAnimationController.onChipAnimationEnd(animationState)
- animationState = if (endState == SHOWING_PERSISTENT_DOT && !hasPersistentDot) {
- IDLE
- } else {
- endState
- }
- }
-
- override fun onAnimationStart(p0: Animator?) {
- chipAnimationController.onChipAnimationStart(viewCreator, animationState)
- }
- }
}
/**
@@ -344,16 +320,14 @@
* create space for the chip animation to display. This means hiding the system elements in the
* status bar and keyguard.
*
- * TODO: the chip animation really only has one client, we can probably remove it from this
- * interface
- *
* The value animators themselves are simple animators from 0.0 to 1.0. Listeners can apply any
* interpolation they choose but realistically these are most likely to be simple alpha transitions
*/
interface SystemStatusAnimationCallback {
- @JvmDefault fun onSystemChromeAnimationUpdate(animator: ValueAnimator) {}
- @JvmDefault fun onSystemChromeAnimationStart() {}
- @JvmDefault fun onSystemChromeAnimationEnd() {}
+ /** Implement this method to return an [Animator] or [AnimatorSet] that presents the chip */
+ fun onSystemEventAnimationBegin(): Animator? { return null }
+ /** Implement this method to return an [Animator] or [AnimatorSet] that hides the chip */
+ fun onSystemEventAnimationFinish(hasPersistentDot: Boolean): Animator? { return null }
// Best method name, change my mind
@JvmDefault
@@ -363,50 +337,61 @@
@JvmDefault fun onHidePersistentDot(): Animator? { return null }
}
-interface SystemStatusChipAnimationCallback {
- fun onChipAnimationUpdate(animator: ValueAnimator, @SystemAnimationState state: Int) {}
-
- fun onChipAnimationStart(
- viewCreator: ViewCreator,
- @SystemAnimationState state: Int
- ) {}
-
- fun onChipAnimationEnd(@SystemAnimationState state: Int) {}
-}
-
/**
+ * Animation state IntDef
*/
@Retention(AnnotationRetention.SOURCE)
@IntDef(
value = [
- IDLE, ANIMATING_IN, RUNNING_CHIP_ANIM, ANIMATING_OUT, SHOWING_PERSISTENT_DOT
+ IDLE,
+ ANIMATION_QUEUED,
+ ANIMATING_IN,
+ RUNNING_CHIP_ANIM,
+ ANIMATING_OUT,
+ SHOWING_PERSISTENT_DOT
]
)
annotation class SystemAnimationState
/** No animation is in progress */
const val IDLE = 0
+/** An animation is queued, and awaiting the debounce period */
+const val ANIMATION_QUEUED = 1
/** System is animating out, and chip is animating in */
-const val ANIMATING_IN = 1
+const val ANIMATING_IN = 2
/** Chip has animated in and is awaiting exit animation, and optionally playing its own animation */
-const val RUNNING_CHIP_ANIM = 2
+const val RUNNING_CHIP_ANIM = 3
/** Chip is animating away and system is animating back */
-const val ANIMATING_OUT = 3
+const val ANIMATING_OUT = 4
/** Chip has animated away, and the persistent dot is showing */
-const val SHOWING_PERSISTENT_DOT = 4
+const val SHOWING_PERSISTENT_DOT = 5
+
+/** Commonly-needed interpolators can go here */
+@JvmField val STATUS_BAR_X_MOVE_OUT = PathInterpolator(0.33f, 0f, 0f, 1f)
+@JvmField val STATUS_BAR_X_MOVE_IN = PathInterpolator(0f, 0f, 0f, 1f)
+/**
+ * Status chip animation to dot have multiple stages of motion, the _1 and _2 interpolators should
+ * be used in succession
+ */
+val STATUS_CHIP_WIDTH_TO_DOT_KEYFRAME_1 = PathInterpolator(0.44f, 0f, 0.25f, 1f)
+val STATUS_CHIP_WIDTH_TO_DOT_KEYFRAME_2 = PathInterpolator(0.3f, 0f, 0.26f, 1f)
+val STATUS_CHIP_HEIGHT_TO_DOT_KEYFRAME_1 = PathInterpolator(0.4f, 0f, 0.17f, 1f)
+val STATUS_CHIP_HEIGHT_TO_DOT_KEYFRAME_2 = PathInterpolator(0.3f, 0f, 0f, 1f)
+val STATUS_CHIP_MOVE_TO_DOT = PathInterpolator(0f, 0f, 0.05f, 1f)
private const val TAG = "SystemStatusAnimationScheduler"
-private const val DELAY = 0L
+private const val DEBOUNCE_DELAY = 100L
/**
- * The total time spent animation should be 1500ms. The entrance animation is how much time
- * we give to the system to animate system elements out of the way. Total chip animation length
- * will be equivalent to 2*chip_anim_length + display_length
+ * The total time spent on the chip animation is 1500ms, broken up into 3 sections:
+ * - 500ms to animate the chip in (including animating system icons away)
+ * - 500ms holding the chip on screen
+ * - 500ms to animate the chip away (and system icons back)
+ *
+ * So DISPLAY_LENGTH should be the sum of the first 2 phases, while the final 500ms accounts for
+ * the actual animation
*/
-private const val ENTRANCE_ANIM_LENGTH = 250L
-private const val CHIP_ANIM_LENGTH = 250L
-// 1s + entrance time + chip anim_length
-private const val DISPLAY_LENGTH = 1500L
+private const val DISPLAY_LENGTH = 1000L
private const val MIN_UPTIME: Long = 5 * 1000
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationLaunchAnimatorController.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationLaunchAnimatorController.kt
index 7fbb0f1..02aa1f2 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationLaunchAnimatorController.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationLaunchAnimatorController.kt
@@ -25,7 +25,7 @@
@JvmOverloads
fun getAnimatorController(
notification: ExpandableNotificationRow,
- onFinishAnimationCallback: Runnable = Runnable {}
+ onFinishAnimationCallback: Runnable? = null
): NotificationLaunchAnimatorController {
return NotificationLaunchAnimatorController(
notificationShadeWindowViewController,
@@ -49,7 +49,7 @@
private val headsUpManager: HeadsUpManagerPhone,
private val notification: ExpandableNotificationRow,
private val jankMonitor: InteractionJankMonitor,
- private val onFinishAnimationCallback: Runnable
+ private val onFinishAnimationCallback: Runnable?
) : ActivityLaunchAnimator.Controller {
companion object {
@@ -123,7 +123,7 @@
if (!willAnimate) {
removeHun(animate = true)
- onFinishAnimationCallback.run()
+ onFinishAnimationCallback?.run()
}
}
@@ -142,7 +142,7 @@
notificationShadeWindowViewController.setExpandAnimationRunning(false)
notificationEntry.isExpandAnimationRunning = false
removeHun(animate = true)
- onFinishAnimationCallback.run()
+ onFinishAnimationCallback?.run()
}
override fun onLaunchAnimationStart(isExpandingFullyAbove: Boolean) {
@@ -162,7 +162,7 @@
notificationListContainer.setExpandingNotification(null)
applyParams(null)
removeHun(animate = false)
- onFinishAnimationCallback.run()
+ onFinishAnimationCallback?.run()
}
private fun applyParams(params: ExpandAnimationParameters?) {
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 fca2aa1..577d536 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
@@ -163,10 +163,13 @@
}
/**
- * @return The background of this view.
+ * @param width The actual width to apply to the background view.
*/
- public NotificationBackgroundView getBackgroundNormal() {
- return mBackgroundNormal;
+ public void setBackgroundWidth(int width) {
+ if (mBackgroundNormal == null) {
+ return;
+ }
+ mBackgroundNormal.setActualWidth(width);
}
@Override
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 c237e1d..e479509 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,7 +79,6 @@
import com.android.internal.util.ContrastColorUtil;
import com.android.internal.widget.CachingIconView;
import com.android.internal.widget.CallLayout;
-import com.android.systemui.Dependency;
import com.android.systemui.R;
import com.android.systemui.animation.Interpolators;
import com.android.systemui.classifier.FalsingCollector;
@@ -90,6 +89,7 @@
import com.android.systemui.plugins.statusbar.StatusBarStateController;
import com.android.systemui.statusbar.NotificationMediaManager;
import com.android.systemui.statusbar.RemoteInputController;
+import com.android.systemui.statusbar.SmartReplyController;
import com.android.systemui.statusbar.StatusBarIconView;
import com.android.systemui.statusbar.notification.AboveShelfChangedListener;
import com.android.systemui.statusbar.notification.ExpandAnimationParameters;
@@ -111,10 +111,11 @@
import com.android.systemui.statusbar.notification.stack.NotificationChildrenContainer;
import com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayout;
import com.android.systemui.statusbar.notification.stack.SwipeableView;
-import com.android.systemui.statusbar.phone.KeyguardBypassController;
import com.android.systemui.statusbar.phone.CentralSurfaces;
+import com.android.systemui.statusbar.phone.KeyguardBypassController;
import com.android.systemui.statusbar.policy.HeadsUpManager;
import com.android.systemui.statusbar.policy.InflatedSmartReplyState;
+import com.android.systemui.statusbar.policy.SmartReplyConstants;
import com.android.systemui.statusbar.policy.dagger.RemoteInputViewSubcomponent;
import com.android.systemui.util.Compile;
import com.android.systemui.util.DumpUtilsKt;
@@ -169,6 +170,7 @@
private RowContentBindStage mRowContentBindStage;
private PeopleNotificationIdentifier mPeopleNotificationIdentifier;
private Optional<BubblesManager> mBubblesManagerOptional;
+ private MetricsLogger mMetricsLogger;
private int mIconTransformContentShift;
private int mMaxHeadsUpHeightBeforeN;
private int mMaxHeadsUpHeightBeforeP;
@@ -304,8 +306,7 @@
final boolean wasExpanded = mGroupExpansionManager.isGroupExpanded(mEntry);
boolean nowExpanded = mGroupExpansionManager.toggleGroupExpansion(mEntry);
mOnExpandClickListener.onExpandClicked(mEntry, v, nowExpanded);
- MetricsLogger.action(mContext, MetricsEvent.ACTION_NOTIFICATION_GROUP_EXPANDER,
- nowExpanded);
+ mMetricsLogger.action(MetricsEvent.ACTION_NOTIFICATION_GROUP_EXPANDER, nowExpanded);
onExpansionChanged(true /* userAction */, wasExpanded);
} else if (mEnableNonGroupedNotificationExpand) {
if (v.isAccessibilityFocused()) {
@@ -327,8 +328,7 @@
}
notifyHeightChanged(true);
mOnExpandClickListener.onExpandClicked(mEntry, v, nowExpanded);
- MetricsLogger.action(mContext, MetricsEvent.ACTION_NOTIFICATION_EXPANDER,
- nowExpanded);
+ mMetricsLogger.action(MetricsEvent.ACTION_NOTIFICATION_EXPANDER, nowExpanded);
}
}
};
@@ -1271,7 +1271,7 @@
addView(mMenuRow.getMenuView(), menuIndex);
}
for (NotificationContentView l : mLayouts) {
- l.initView();
+ l.reinflate();
l.reInflateViews();
}
mEntry.getSbn().clearPackageContext();
@@ -1464,7 +1464,7 @@
* @param fromAccessibility whether this dismiss is coming from an accessibility action
*/
public void performDismiss(boolean fromAccessibility) {
- Dependency.get(MetricsLogger.class).count(NotificationCounters.NOTIFICATION_DISMISSED, 1);
+ mMetricsLogger.count(NotificationCounters.NOTIFICATION_DISMISSED, 1);
dismiss(fromAccessibility);
if (mEntry.isDismissable()) {
if (mOnUserInteractionCallback != null) {
@@ -1600,7 +1600,10 @@
PeopleNotificationIdentifier peopleNotificationIdentifier,
OnUserInteractionCallback onUserInteractionCallback,
Optional<BubblesManager> bubblesManagerOptional,
- NotificationGutsManager gutsManager) {
+ NotificationGutsManager gutsManager,
+ MetricsLogger metricsLogger,
+ SmartReplyConstants smartReplyConstants,
+ SmartReplyController smartReplyController) {
mEntry = entry;
mAppName = appName;
if (mMenuRow == null) {
@@ -1623,15 +1626,18 @@
mFalsingManager = falsingManager;
mFalsingCollector = falsingCollector;
mStatusBarStateController = statusBarStateController;
-
mPeopleNotificationIdentifier = peopleNotificationIdentifier;
for (NotificationContentView l : mLayouts) {
- l.setPeopleNotificationIdentifier(mPeopleNotificationIdentifier);
- l.setRemoteInputViewSubcomponentFactory(rivSubcomponentFactory);
+ l.initialize(
+ mPeopleNotificationIdentifier,
+ rivSubcomponentFactory,
+ smartReplyConstants,
+ smartReplyController);
}
mOnUserInteractionCallback = onUserInteractionCallback;
mBubblesManagerOptional = bubblesManagerOptional;
mNotificationGutsManager = gutsManager;
+ mMetricsLogger = metricsLogger;
cacheIsSystemNotification();
}
@@ -3127,7 +3133,7 @@
if (mGroupMembershipManager.isGroupSummary(mEntry)) {
event = MetricsEvent.ACTION_NOTIFICATION_GROUP_GESTURE_EXPANDER;
}
- MetricsLogger.action(mContext, event, userExpanded);
+ mMetricsLogger.action(event, userExpanded);
}
@Override
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 c4beb5b..599039d 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
@@ -27,6 +27,7 @@
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
+import com.android.internal.logging.MetricsLogger;
import com.android.systemui.classifier.FalsingCollector;
import com.android.systemui.flags.FeatureFlags;
import com.android.systemui.flags.Flags;
@@ -35,6 +36,7 @@
import com.android.systemui.plugins.statusbar.StatusBarStateController;
import com.android.systemui.shared.plugins.PluginManager;
import com.android.systemui.statusbar.NotificationMediaManager;
+import com.android.systemui.statusbar.SmartReplyController;
import com.android.systemui.statusbar.notification.FeedbackIcon;
import com.android.systemui.statusbar.notification.collection.NotificationEntry;
import com.android.systemui.statusbar.notification.collection.render.GroupExpansionManager;
@@ -49,6 +51,7 @@
import com.android.systemui.statusbar.notification.stack.NotificationListContainer;
import com.android.systemui.statusbar.phone.KeyguardBypassController;
import com.android.systemui.statusbar.policy.HeadsUpManager;
+import com.android.systemui.statusbar.policy.SmartReplyConstants;
import com.android.systemui.statusbar.policy.dagger.RemoteInputViewSubcomponent;
import com.android.systemui.util.time.SystemClock;
import com.android.systemui.wmshell.BubblesManager;
@@ -82,6 +85,7 @@
private final HeadsUpManager mHeadsUpManager;
private final ExpandableNotificationRow.OnExpandClickListener mOnExpandClickListener;
private final StatusBarStateController mStatusBarStateController;
+ private final MetricsLogger mMetricsLogger;
private final ExpandableNotificationRow.ExpansionLogger mExpansionLogger =
this::logNotificationExpansion;
@@ -94,16 +98,21 @@
private final boolean mAllowLongPress;
private final PeopleNotificationIdentifier mPeopleNotificationIdentifier;
private final Optional<BubblesManager> mBubblesManagerOptional;
+ private final SmartReplyConstants mSmartReplyConstants;
+ private final SmartReplyController mSmartReplyController;
private final ExpandableNotificationRowDragController mDragController;
@Inject
public ExpandableNotificationRowController(
ExpandableNotificationRow view,
- NotificationListContainer listContainer,
- RemoteInputViewSubcomponent.Factory rivSubcomponentFactory,
ActivatableNotificationViewController activatableNotificationViewController,
+ RemoteInputViewSubcomponent.Factory rivSubcomponentFactory,
+ MetricsLogger metricsLogger,
+ NotificationListContainer listContainer,
NotificationMediaManager mediaManager,
+ SmartReplyConstants smartReplyConstants,
+ SmartReplyController smartReplyController,
PluginManager pluginManager,
SystemClock clock,
@AppName String appName,
@@ -152,6 +161,9 @@
mPeopleNotificationIdentifier = peopleNotificationIdentifier;
mBubblesManagerOptional = bubblesManagerOptional;
mDragController = dragController;
+ mMetricsLogger = metricsLogger;
+ mSmartReplyConstants = smartReplyConstants;
+ mSmartReplyController = smartReplyController;
}
/**
@@ -179,7 +191,10 @@
mPeopleNotificationIdentifier,
mOnUserInteractionCallback,
mBubblesManagerOptional,
- mNotificationGutsManager
+ mNotificationGutsManager,
+ mMetricsLogger,
+ mSmartReplyConstants,
+ mSmartReplyController
);
mView.setDescendantFocusability(ViewGroup.FOCUS_BLOCK_DESCENDANTS);
if (mAllowLongPress) {
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 9cb5dc5..b9c71132 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
@@ -39,7 +39,6 @@
import android.widget.LinearLayout;
import com.android.internal.annotations.VisibleForTesting;
-import com.android.systemui.Dependency;
import com.android.systemui.R;
import com.android.systemui.plugins.statusbar.NotificationMenuRowPlugin;
import com.android.systemui.statusbar.RemoteInputController;
@@ -94,7 +93,6 @@
private final Rect mClipBounds = new Rect();
private int mMinContractedHeight;
- private int mNotificationContentMarginEnd;
private View mContractedChild;
private View mExpandedChild;
private View mHeadsUpChild;
@@ -116,7 +114,7 @@
private NotificationViewWrapper mContractedWrapper;
private NotificationViewWrapper mExpandedWrapper;
private NotificationViewWrapper mHeadsUpWrapper;
- private HybridGroupManager mHybridGroupManager;
+ private final HybridGroupManager mHybridGroupManager;
private int mClipTopAmount;
private int mContentHeight;
private int mVisibleType = VISIBLE_TYPE_NONE;
@@ -128,7 +126,6 @@
private int mHeadsUpHeight;
private int mNotificationMaxHeight;
private NotificationEntry mNotificationEntry;
- private GroupMembershipManager mGroupMembershipManager;
private RemoteInputController mRemoteInputController;
private Runnable mExpandedVisibleListener;
private PeopleNotificationIdentifier mPeopleIdentifier;
@@ -184,7 +181,6 @@
private boolean mFocusOnVisibilityChange;
private boolean mHeadsUpAnimatingAway;
private int mClipBottomAmount;
- private boolean mIsLowPriority;
private boolean mIsContentExpandable;
private boolean mRemoteInputVisible;
private int mUnrestrictedContentHeight;
@@ -192,16 +188,23 @@
public NotificationContentView(Context context, AttributeSet attrs) {
super(context, attrs);
mHybridGroupManager = new HybridGroupManager(getContext());
- mSmartReplyConstants = Dependency.get(SmartReplyConstants.class);
- mSmartReplyController = Dependency.get(SmartReplyController.class);
- initView();
+ reinflate();
}
- public void initView() {
+ public void initialize(
+ PeopleNotificationIdentifier peopleNotificationIdentifier,
+ RemoteInputViewSubcomponent.Factory rivSubcomponentFactory,
+ SmartReplyConstants smartReplyConstants,
+ SmartReplyController smartReplyController) {
+ mPeopleIdentifier = peopleNotificationIdentifier;
+ mRemoteInputSubcomponentFactory = rivSubcomponentFactory;
+ mSmartReplyConstants = smartReplyConstants;
+ mSmartReplyController = smartReplyController;
+ }
+
+ public void reinflate() {
mMinContractedHeight = getResources().getDimensionPixelSize(
R.dimen.min_notification_layout_height);
- mNotificationContentMarginEnd = getResources().getDimensionPixelSize(
- com.android.internal.R.dimen.notification_content_margin_end);
}
public void setHeights(int smallHeight, int headsUpMaxHeight, int maxHeight) {
@@ -413,7 +416,10 @@
if (mExpandedRemoteInput != null) {
mExpandedRemoteInput.onNotificationUpdateOrReset();
if (mExpandedRemoteInput.isActive()) {
- mPreviousExpandedRemoteInputIntent = mExpandedRemoteInput.getPendingIntent();
+ if (mExpandedRemoteInputController != null) {
+ mPreviousExpandedRemoteInputIntent =
+ mExpandedRemoteInputController.getPendingIntent();
+ }
mCachedExpandedRemoteInput = mExpandedRemoteInput;
mCachedExpandedRemoteInputViewController = mExpandedRemoteInputController;
mExpandedRemoteInput.dispatchStartTemporaryDetach();
@@ -460,7 +466,10 @@
if (mHeadsUpRemoteInput != null) {
mHeadsUpRemoteInput.onNotificationUpdateOrReset();
if (mHeadsUpRemoteInput.isActive()) {
- mPreviousHeadsUpRemoteInputIntent = mHeadsUpRemoteInput.getPendingIntent();
+ if (mHeadsUpRemoteInputController != null) {
+ mPreviousHeadsUpRemoteInputIntent =
+ mHeadsUpRemoteInputController.getPendingIntent();
+ }
mCachedHeadsUpRemoteInput = mHeadsUpRemoteInput;
mCachedHeadsUpRemoteInputViewController = mHeadsUpRemoteInputController;
mHeadsUpRemoteInput.dispatchStartTemporaryDetach();
@@ -961,14 +970,16 @@
private void transferRemoteInputFocus(int visibleType) {
if (visibleType == VISIBLE_TYPE_HEADSUP
- && mHeadsUpRemoteInput != null
- && (mExpandedRemoteInput != null && mExpandedRemoteInput.isActive())) {
- mHeadsUpRemoteInput.stealFocusFrom(mExpandedRemoteInput);
+ && mHeadsUpRemoteInputController != null
+ && mExpandedRemoteInputController != null
+ && mExpandedRemoteInputController.isActive()) {
+ mHeadsUpRemoteInputController.stealFocusFrom(mExpandedRemoteInputController);
}
if (visibleType == VISIBLE_TYPE_EXPANDED
- && mExpandedRemoteInput != null
- && (mHeadsUpRemoteInput != null && mHeadsUpRemoteInput.isActive())) {
- mExpandedRemoteInput.stealFocusFrom(mHeadsUpRemoteInput);
+ && mExpandedRemoteInputController != null
+ && mHeadsUpRemoteInputController != null
+ && mHeadsUpRemoteInputController.isActive()) {
+ mExpandedRemoteInputController.stealFocusFrom(mHeadsUpRemoteInputController);
}
}
@@ -1313,7 +1324,6 @@
// If we find a matching action in the new notification, focus, otherwise close.
Notification.Action[] actions = entry.getSbn().getNotification().actions;
if (existingPendingIntent != null) {
- result.mView.setPendingIntent(existingPendingIntent);
result.mController.setPendingIntent(existingPendingIntent);
}
if (result.mController.updatePendingIntentFromActions(actions)) {
@@ -1599,7 +1609,6 @@
}
public void setGroupMembershipManager(GroupMembershipManager groupMembershipManager) {
- mGroupMembershipManager = groupMembershipManager;
}
public void setRemoteInputController(RemoteInputController r) {
@@ -1687,10 +1696,6 @@
mContainingNotification = containingNotification;
}
- public void setPeopleNotificationIdentifier(PeopleNotificationIdentifier peopleIdentifier) {
- mPeopleIdentifier = peopleIdentifier;
- }
-
public void requestSelectLayout(boolean needsAnimation) {
selectLayout(needsAnimation, false);
}
@@ -1858,7 +1863,6 @@
}
public void setIsLowPriority(boolean isLowPriority) {
- mIsLowPriority = isLowPriority;
}
public boolean isDimmable() {
@@ -2083,10 +2087,6 @@
return false;
}
- public void setRemoteInputViewSubcomponentFactory(RemoteInputViewSubcomponent.Factory factory) {
- mRemoteInputSubcomponentFactory = factory;
- }
-
private static class RemoteInputViewData {
@Nullable RemoteInputView mView;
@Nullable RemoteInputViewController mController;
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 be1aa10..c89f4d7 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
@@ -217,6 +217,7 @@
private HashSet<View> mFromMoreCardAdditions = new HashSet<>();
private ArrayList<AnimationEvent> mAnimationEvents = new ArrayList<>();
private ArrayList<View> mSwipedOutViews = new ArrayList<>();
+ private NotificationStackSizeCalculator mNotificationStackSizeCalculator;
private final StackStateAnimator mStateAnimator = new StackStateAnimator(this);
private boolean mAnimationsEnabled;
private boolean mChangePositionInProgress;
@@ -415,6 +416,7 @@
private NotificationShelf mShelf;
private int mMaxDisplayedNotifications = -1;
private float mKeyguardBottomPadding = -1;
+ private float mKeyguardNotificationAvailableSpace = -1;
@VisibleForTesting int mStatusBarHeight;
private int mMinInteractionHeight;
private final Rect mClipRect = new Rect();
@@ -757,30 +759,46 @@
} else {
mDebugTextUsedYPositions.clear();
}
- int y = mTopPadding;
- drawDebugInfo(canvas, y, Color.RED, /* label= */ "mTopPadding");
+ int y = 0;
+ drawDebugInfo(canvas, y, Color.RED, /* label= */ "y = " + y);
+
+ y = mTopPadding;
+ drawDebugInfo(canvas, y, Color.RED, /* label= */ "mTopPadding = " + y);
y = getLayoutHeight();
- drawDebugInfo(canvas, y, Color.YELLOW, /* label= */ "getLayoutHeight()");
+ drawDebugInfo(canvas, y, Color.YELLOW, /* label= */ "getLayoutHeight() = " + y);
y = (int) mMaxLayoutHeight;
- drawDebugInfo(canvas, y, Color.MAGENTA, /* label= */ "mMaxLayoutHeight");
+ drawDebugInfo(canvas, y, Color.MAGENTA, /* label= */ "mMaxLayoutHeight = " + y);
if (mKeyguardBottomPadding >= 0) {
y = getHeight() - (int) mKeyguardBottomPadding;
drawDebugInfo(canvas, y, Color.GRAY,
- /* label= */ "getHeight() - mKeyguardBottomPadding");
+ /* label= */ "getHeight() - mKeyguardBottomPadding = " + y);
}
y = getHeight() - getEmptyBottomMargin();
- drawDebugInfo(canvas, y, Color.GREEN, /* label= */ "getHeight() - getEmptyBottomMargin()");
+ drawDebugInfo(canvas, y, Color.GREEN,
+ /* label= */ "getHeight() - getEmptyBottomMargin() = " + y);
y = (int) (mAmbientState.getStackY());
- drawDebugInfo(canvas, y, Color.CYAN, /* label= */ "mAmbientState.getStackY()");
+ drawDebugInfo(canvas, y, Color.CYAN, /* label= */ "mAmbientState.getStackY() = " + y);
y = (int) (mAmbientState.getStackY() + mAmbientState.getStackHeight());
drawDebugInfo(canvas, y, Color.BLUE,
- /* label= */ "mAmbientState.getStackY() + mAmbientState.getStackHeight()");
+ /* label= */ "mAmbientState.getStackY() + mAmbientState.getStackHeight() = " + y);
+
+ y = (int) mAmbientState.getStackY() + mContentHeight;
+ drawDebugInfo(canvas, y, Color.MAGENTA,
+ /* label= */ "mAmbientState.getStackY() + mContentHeight = " + y);
+
+ y = (int) mAmbientState.getStackY() + mIntrinsicContentHeight;
+ drawDebugInfo(canvas, y, Color.YELLOW,
+ /* label= */ "mAmbientState.getStackY() + mIntrinsicContentHeight = " + y);
+
+ y = (int) (mAmbientState.getStackY() + mKeyguardNotificationAvailableSpace);
+ drawDebugInfo(canvas, y, Color.RED, /* label= */
+ "mAmbientState.getStackY() + mKeyguardNotificationAvailableSpace = " + y);
}
private void drawDebugInfo(Canvas canvas, int y, int color, String label) {
@@ -947,13 +965,15 @@
}
private void reinitView() {
- initView(getContext(), mSwipeHelper);
+ initView(getContext(), mSwipeHelper, mNotificationStackSizeCalculator);
}
@ShadeViewRefactor(RefactorComponent.SHADE_VIEW)
- void initView(Context context, NotificationSwipeHelper swipeHelper) {
+ void initView(Context context, NotificationSwipeHelper swipeHelper,
+ NotificationStackSizeCalculator notificationStackSizeCalculator) {
mScroller = new OverScroller(getContext());
mSwipeHelper = swipeHelper;
+ mNotificationStackSizeCalculator = notificationStackSizeCalculator;
setDescendantFocusability(FOCUS_AFTER_DESCENDANTS);
setClipChildren(false);
@@ -1292,14 +1312,13 @@
mOnStackYChanged.accept(listenerNeedsAnimation);
}
if (mQsExpansionFraction <= 0 && !shouldSkipHeightUpdate()) {
- final float endHeight = updateStackEndHeight(
- getHeight(), getEmptyBottomMargin(), mTopPadding);
+ final float endHeight = updateStackEndHeight();
updateStackHeight(endHeight, fraction);
}
}
- public float updateStackEndHeight(float height, float bottomMargin, float topPadding) {
- final float stackEndHeight = Math.max(0f, height - bottomMargin - topPadding);
+ private float updateStackEndHeight() {
+ final float stackEndHeight = Math.max(0f, mIntrinsicContentHeight);
mAmbientState.setStackEndHeight(stackEndHeight);
return stackEndHeight;
}
@@ -2240,48 +2259,10 @@
@ShadeViewRefactor(RefactorComponent.STATE_RESOLVER)
private void updateContentHeight() {
final float scrimTopPadding = mAmbientState.isOnKeyguard() ? 0 : mMinimumPaddings;
- int height = (int) scrimTopPadding;
- float previousPaddingRequest = mPaddingBetweenElements;
- int numShownItems = 0;
- int numShownNotifs = 0;
- boolean finish = false;
- int maxDisplayedNotifications = mMaxDisplayedNotifications;
- ExpandableView previousView = null;
-
- for (int i = 0; i < getChildCount(); i++) {
- ExpandableView expandableView = (ExpandableView) getChildAt(i);
- boolean footerViewOnLockScreen = expandableView == mFooterView && onKeyguard();
-
- if (expandableView.getVisibility() != View.GONE
- && !expandableView.hasNoContentHeight() && !footerViewOnLockScreen) {
-
- boolean limitReached = maxDisplayedNotifications != -1
- && numShownNotifs >= maxDisplayedNotifications;
- final float viewHeight;
- if (limitReached) {
- viewHeight = mShelf.getIntrinsicHeight();
- finish = true;
- } else {
- viewHeight = expandableView.getIntrinsicHeight();
- }
- if (height != 0) {
- height += mPaddingBetweenElements;
- }
- float gapHeight = calculateGapHeight(previousView, expandableView, numShownNotifs);
- height += gapHeight;
- height += viewHeight;
-
- numShownItems++;
- if (viewHeight > 0 || !(expandableView instanceof MediaContainerView)) {
- // Only count the media as a notification if it has a positive height.
- numShownNotifs++;
- }
- previousView = expandableView;
- if (finish) {
- break;
- }
- }
- }
+ final int height =
+ (int) scrimTopPadding + (int) mNotificationStackSizeCalculator.computeHeight(
+ /* notificationStackScrollLayout= */ this, mMaxDisplayedNotifications,
+ mShelf != null ? mShelf.getIntrinsicHeight() : 0);
mIntrinsicContentHeight = height;
// The topPadding can be bigger than the regular padding when qs is expanded, in that
@@ -4924,6 +4905,15 @@
mKeyguardBottomPadding = keyguardBottomPadding;
}
+ /**
+ * For debugging only. Enables to draw a line related to the available size for notifications in
+ * keyguard.
+ */
+ public void setKeyguardAvailableSpaceForDebug(float keyguardNotificationAvailableSpace) {
+ mKeyguardNotificationAvailableSpace = keyguardNotificationAvailableSpace;
+ }
+
+
@ShadeViewRefactor(RefactorComponent.SHADE_VIEW)
public void setShouldShowShelfOnly(boolean shouldShowShelfOnly) {
mShouldShowShelfOnly = shouldShowShelfOnly;
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 6bbecc8..d98f8a7 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
@@ -181,6 +181,7 @@
private final SectionHeaderController mSilentHeaderController;
private final LockscreenShadeTransitionController mLockscreenShadeTransitionController;
private final InteractionJankMonitor mJankMonitor;
+ private final NotificationStackSizeCalculator mNotificationStackSizeCalculator;
private final StackStateLogger mStackStateLogger;
private final NotificationStackScrollLogger mLogger;
@@ -307,6 +308,7 @@
R.dimen.lockscreen_shade_notification_movement);
mTotalDistanceForFullShadeTransition = mResources.getDimensionPixelSize(
R.dimen.lockscreen_shade_qs_transition_distance);
+ mNotificationStackSizeCalculator.updateResources();
}
private final StatusBarStateController.StateListener mStateListener =
@@ -662,7 +664,8 @@
ShadeController shadeController,
InteractionJankMonitor jankMonitor,
StackStateLogger stackLogger,
- NotificationStackScrollLogger logger) {
+ NotificationStackScrollLogger logger,
+ NotificationStackSizeCalculator notificationStackSizeCalculator) {
mStackStateLogger = stackLogger;
mLogger = logger;
mAllowLongPress = allowLongPress;
@@ -688,6 +691,7 @@
mCentralSurfaces = centralSurfaces;
mScrimController = scrimController;
mJankMonitor = jankMonitor;
+ mNotificationStackSizeCalculator = notificationStackSizeCalculator;
groupManager.registerGroupExpansionChangeListener(
(changedRow, expanded) -> mView.onGroupExpandChanged(changedRow, expanded));
legacyGroupManager.registerGroupChangeListener(new OnGroupChangeListener() {
@@ -758,7 +762,7 @@
});
}
- mView.initView(mView.getContext(), mSwipeHelper);
+ mView.initView(mView.getContext(), mSwipeHelper, mNotificationStackSizeCalculator);
mView.setKeyguardBypassEnabled(mKeyguardBypassController.getBypassEnabled());
mKeyguardBypassController
.registerOnBypassStateChangedListener(mView::setKeyguardBypassEnabled);
@@ -907,6 +911,13 @@
return mView.getTop();
}
+ /**
+ * @return the bottom of the view.
+ */
+ public int getBottom() {
+ return mView.getBottom();
+ }
+
public float getTranslationX() {
return mView.getTranslationX();
}
@@ -1296,10 +1307,16 @@
* appear on the keyguard.
* Setting a negative number will disable rendering this line.
*/
- public void setKeyguardBottomPadding(float keyguardBottomPadding) {
+ public void setKeyguardBottomPaddingForDebug(float keyguardBottomPadding) {
mView.setKeyguardBottomPadding(keyguardBottomPadding);
}
+ /** For debugging only. */
+ public void mKeyguardNotificationAvailableSpaceForDebug(
+ float keyguardNotificationAvailableSpace) {
+ mView.setKeyguardAvailableSpaceForDebug(keyguardNotificationAvailableSpace);
+ }
+
public RemoteInputController.Delegate createDelegate() {
return new RemoteInputController.Delegate() {
public void setRemoteInputActive(NotificationEntry entry,
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackSizeCalculator.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackSizeCalculator.kt
new file mode 100644
index 0000000..3f971552
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackSizeCalculator.kt
@@ -0,0 +1,261 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.statusbar.notification.stack
+
+import android.content.res.Resources
+import android.util.Log
+import android.view.View.GONE
+import com.android.systemui.R
+import com.android.systemui.dagger.SysUISingleton
+import com.android.systemui.dagger.qualifiers.Main
+import com.android.systemui.statusbar.NotificationLockscreenUserManager
+import com.android.systemui.statusbar.StatusBarState.KEYGUARD
+import com.android.systemui.statusbar.SysuiStatusBarStateController
+import com.android.systemui.statusbar.notification.collection.legacy.NotificationGroupManagerLegacy
+import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow
+import com.android.systemui.statusbar.notification.row.ExpandableView
+import com.android.systemui.util.children
+import javax.inject.Inject
+import kotlin.math.max
+import kotlin.properties.Delegates.notNull
+
+private const val TAG = "NotificationStackSizeCalculator"
+private const val DEBUG = false
+
+/** Calculates number of notifications to display and the height of the notification stack. */
+@SysUISingleton
+class NotificationStackSizeCalculator
+@Inject
+constructor(
+ private val groupManager: NotificationGroupManagerLegacy,
+ private val lockscreenUserManager: NotificationLockscreenUserManager,
+ private val statusBarStateController: SysuiStatusBarStateController,
+ @Main private val resources: Resources
+) {
+
+ /**
+ * Maximum # notifications to show on Keyguard; extras will be collapsed in an overflow shelf.
+ * If there are exactly 1 + mMaxKeyguardNotifications, and they fit in the available space
+ * (considering the overflow shelf is not displayed in this case), then all notifications are
+ * shown.
+ */
+ private var maxKeyguardNotifications by notNull<Int>()
+
+ /**
+ * Minimum space between two notifications. There might be more space, see [calculateGapHeight].
+ */
+ private var notificationPadding by notNull<Int>()
+
+ init {
+ updateResources()
+ }
+
+ /**
+ * Given the [availableSpace] constraint, calculates how many notification to show.
+ *
+ * This number is only valid in keyguard.
+ *
+ * @param availableSpace space for notifications. This doesn't include the space for the shelf.
+ */
+ fun computeMaxKeyguardNotifications(
+ stack: NotificationStackScrollLayout,
+ availableSpace: Float,
+ shelfHeight: Float
+ ): Int {
+ log {
+ "computeMaxKeyguardNotifications(" +
+ "availableSpace=$availableSpace shelfHeight=$shelfHeight)"
+ }
+
+ val children: Sequence<ExpandableView> = stack.childrenSequence
+ var remainingSpace: Float = availableSpace
+ var count = 0
+ var previous: ExpandableView? = null
+ val onLockscreen = true
+ val showableRows = children.filter { it.isShowable(onLockscreen) }
+ val showableRowsCount = showableRows.count()
+ showableRows.forEachIndexed { i, current ->
+ val spaceNeeded = current.spaceNeeded(count, previous, stack, onLockscreen)
+ previous = current
+ log { "\ti=$i spaceNeeded=$spaceNeeded remainingSpace=$remainingSpace" }
+
+ if (remainingSpace - spaceNeeded >= 0 && count < maxKeyguardNotifications) {
+ count += 1
+ remainingSpace -= spaceNeeded
+ } else if (remainingSpace - spaceNeeded > -shelfHeight && i == showableRowsCount - 1) {
+ log { "Showing all notifications. Shelf is not be needed." }
+ // If this is the last one, and it fits using the space shelf would use, then we can
+ // display it, as the shelf will not be needed (as all notifications are shown).
+ return count + 1
+ } else {
+ log {
+ "No more fit. Returning $count. Space used: ${availableSpace - remainingSpace}"
+ }
+ return count
+ }
+ }
+ log { "All fit. Returning $count" }
+ return count
+ }
+
+ /**
+ * Given the [maxNotifications] constraint, calculates the height of the
+ * [NotificationStackScrollLayout]. This might or might not be in keyguard.
+ *
+ * @param stack stack containing notifications as children.
+ * @param maxNotifications Maximum number of notifications. When reached, the others will go
+ * into the shelf.
+ * @param shelfHeight height of the shelf. It might be zero.
+ *
+ * @return height of the stack, including shelf height, if needed.
+ */
+ fun computeHeight(
+ stack: NotificationStackScrollLayout,
+ maxNotifications: Int,
+ shelfHeight: Float
+ ): Float {
+ val children: Sequence<ExpandableView> = stack.childrenSequence
+ val maxNotificationsArg = infiniteIfNegative(maxNotifications)
+ var height = 0f
+ var previous: ExpandableView? = null
+ var count = 0
+ val onLockscreen = onLockscreen()
+
+ log { "computeHeight(maxNotification=$maxNotifications, shelf=$shelfHeight" }
+ children.filter { it.isShowable(onLockscreen) }.forEach { current ->
+ if (count < maxNotificationsArg) {
+ val spaceNeeded = current.spaceNeeded(count, previous, stack, onLockscreen)
+ log { "\ti=$count spaceNeeded=$spaceNeeded" }
+ height += spaceNeeded
+ count += 1
+ } else {
+ height += shelfHeight
+ log { "returning height with shelf -> $height" }
+ return height
+ }
+ previous = current
+ }
+ log { "Returning height without shelf -> $height" }
+ return height
+ }
+
+ fun updateResources() {
+ maxKeyguardNotifications =
+ infiniteIfNegative(resources.getInteger(R.integer.keyguard_max_notification_count))
+
+ notificationPadding =
+ max(1, resources.getDimensionPixelSize(R.dimen.notification_divider_height))
+ }
+
+ private val NotificationStackScrollLayout.childrenSequence: Sequence<ExpandableView>
+ get() = children.map { it as ExpandableView }
+
+ private fun onLockscreen() = statusBarStateController.state == KEYGUARD
+
+ private fun ExpandableView.spaceNeeded(
+ visibleIndex: Int,
+ previousView: ExpandableView?,
+ stack: NotificationStackScrollLayout,
+ onLockscreen: Boolean
+ ): Float {
+ assert(isShowable(onLockscreen))
+ var size =
+ if (onLockscreen) {
+ getMinHeight(/* ignoreTemporaryStates= */ true).toFloat()
+ } else {
+ intrinsicHeight.toFloat()
+ }
+ if (visibleIndex != 0) {
+ size += notificationPadding
+ }
+ size += calculateGapHeight(stack, previousView, visibleIndex)
+ return size
+ }
+
+ private fun ExpandableView.isShowable(onLockscreen: Boolean): Boolean {
+ if (visibility == GONE || hasNoContentHeight()) return false
+ if (onLockscreen) {
+ when (this) {
+ is ExpandableNotificationRow -> {
+ if (isSummaryOfSuppressedGroup() || !canShowViewOnLockscreen() || isRemoved) {
+ return false
+ }
+ }
+ is MediaContainerView -> if (intrinsicHeight == 0) return false
+ else -> return false
+ }
+ }
+ return true
+ }
+
+ private fun ExpandableView.calculateGapHeight(
+ stack: NotificationStackScrollLayout,
+ previous: ExpandableView?,
+ visibleIndex: Int
+ ) = stack.calculateGapHeight(previous, /* current= */ this, visibleIndex)
+
+ private fun ExpandableNotificationRow.isSummaryOfSuppressedGroup() =
+ groupManager.isSummaryOfSuppressedGroup(entry.sbn)
+
+ /**
+ * Can a view be shown on the lockscreen when calculating the number of allowed notifications to
+ * show?
+ *
+ * @return `true` if it can be shown.
+ */
+ private fun ExpandableView.canShowViewOnLockscreen(): Boolean {
+ if (hasNoContentHeight()) {
+ return false
+ }
+ if (this is ExpandableNotificationRow && !canShowRowOnLockscreen()) {
+ return false
+ } else if (visibility == GONE) {
+ return false
+ }
+ return true
+ }
+
+ /**
+ * Can a row be shown on the lockscreen when calculating the number of allowed notifications to
+ * show?
+ *
+ * @return true if it can be shown
+ */
+ private fun ExpandableNotificationRow.canShowRowOnLockscreen(): Boolean {
+ if (isSummaryOfSuppressedGroup()) {
+ return false
+ }
+ if (!lockscreenUserManager.shouldShowOnKeyguard(entry)) {
+ return false
+ }
+ return !isRemoved
+ }
+
+ private fun log(s: () -> String) {
+ if (DEBUG) {
+ Log.d(TAG, s())
+ }
+ }
+
+ /** Returns infinite when [v] is negative. Useful in case a resource doesn't limit when -1. */
+ private fun infiniteIfNegative(v: Int): Int =
+ if (v < 0) {
+ Int.MAX_VALUE
+ } else {
+ v
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/StackScrollAlgorithm.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/StackScrollAlgorithm.java
index 952cd9a..e1f8c35 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/StackScrollAlgorithm.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/StackScrollAlgorithm.java
@@ -202,12 +202,10 @@
float newHeight = state.height;
float newNotificationEnd = newYTranslation + newHeight;
boolean isHeadsUp = (child instanceof ExpandableNotificationRow) && child.isPinned();
- final boolean shadeClosedWithHUN =
- ambientState.isShadeOpening() && !ambientState.isShadeExpanded();
if (mClipNotificationScrollToTop
&& (!state.inShelf || (isHeadsUp && !firstHeadsUp))
&& newYTranslation < clipStart
- && shadeClosedWithHUN) {
+ && !ambientState.isShadeExpanded()) {
// The previous view is overlapping on top, clip!
float overlapAmount = clipStart - newYTranslation;
state.clipTopAmount = (int) overlapAmount;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardClockPositionAlgorithm.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardClockPositionAlgorithm.java
index 732e5f0..602d075 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardClockPositionAlgorithm.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardClockPositionAlgorithm.java
@@ -23,6 +23,7 @@
import android.content.res.Resources;
import android.util.MathUtils;
+import com.android.keyguard.BouncerPanelExpansionCalculator;
import com.android.keyguard.KeyguardStatusView;
import com.android.systemui.R;
import com.android.systemui.animation.Interpolators;
@@ -169,7 +170,8 @@
boolean isSplitShade, float udfpsTop, float clockBottom, boolean isClockTopAligned) {
mMinTopMargin = keyguardStatusBarHeaderHeight + Math.max(mContainerTopPadding,
userSwitchHeight);
- mPanelExpansion = panelExpansion;
+ mPanelExpansion = BouncerPanelExpansionCalculator
+ .getKeyguardClockScaledExpansion(panelExpansion);
mKeyguardStatusHeight = keyguardStatusHeight + mStatusViewBottomMargin;
mUserSwitchHeight = userSwitchHeight;
mUserSwitchPreferredY = userSwitchPreferredY;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardLiftController.kt b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardLiftController.kt
index 571c10b..64b0b4e 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardLiftController.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardLiftController.kt
@@ -16,34 +16,52 @@
package com.android.systemui.statusbar.phone
+import android.content.Context
+import android.content.pm.PackageManager
import android.hardware.Sensor
import android.hardware.TriggerEvent
import android.hardware.TriggerEventListener
import com.android.keyguard.KeyguardUpdateMonitor
import com.android.keyguard.KeyguardUpdateMonitorCallback
+import com.android.systemui.CoreStartable
import com.android.systemui.Dumpable
+import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.dump.DumpManager
import com.android.systemui.plugins.statusbar.StatusBarStateController
import com.android.systemui.util.Assert
import com.android.systemui.util.sensors.AsyncSensorManager
import java.io.FileDescriptor
import java.io.PrintWriter
+import javax.inject.Inject
-class KeyguardLiftController constructor(
+/**
+ * Triggers face auth on lift when the device is showing the lock screen. Only initialized
+ * if face auth is supported on the device. Not to be confused with the lift to wake gesture
+ * which is handled by {@link com.android.server.policy.PhoneWindowManager}.
+ */
+@SysUISingleton
+class KeyguardLiftController @Inject constructor(
+ private val context: Context,
private val statusBarStateController: StatusBarStateController,
private val asyncSensorManager: AsyncSensorManager,
private val keyguardUpdateMonitor: KeyguardUpdateMonitor,
- dumpManager: DumpManager
-) : StatusBarStateController.StateListener, Dumpable, KeyguardUpdateMonitorCallback() {
+ private val dumpManager: DumpManager
+) : Dumpable, CoreStartable(context) {
private val pickupSensor = asyncSensorManager.getDefaultSensor(Sensor.TYPE_PICK_UP_GESTURE)
private var isListening = false
private var bouncerVisible = false
- init {
+ override fun start() {
+ if (context.packageManager.hasSystemFeature(PackageManager.FEATURE_FACE)) {
+ init()
+ }
+ }
+
+ private fun init() {
dumpManager.registerDumpable(javaClass.name, this)
- statusBarStateController.addCallback(this)
- keyguardUpdateMonitor.registerCallback(this)
+ statusBarStateController.addCallback(statusBarStateListener)
+ keyguardUpdateMonitor.registerCallback(keyguardUpdateMonitorCallback)
updateListeningState()
}
@@ -58,17 +76,21 @@
}
}
- override fun onDozingChanged(isDozing: Boolean) {
- updateListeningState()
+ private val keyguardUpdateMonitorCallback = object : KeyguardUpdateMonitorCallback() {
+ override fun onKeyguardBouncerChanged(bouncer: Boolean) {
+ bouncerVisible = bouncer
+ updateListeningState()
+ }
+
+ override fun onKeyguardVisibilityChanged(showing: Boolean) {
+ updateListeningState()
+ }
}
- override fun onKeyguardBouncerChanged(bouncer: Boolean) {
- bouncerVisible = bouncer
- updateListeningState()
- }
-
- override fun onKeyguardVisibilityChanged(showing: Boolean) {
- updateListeningState()
+ private val statusBarStateListener = object : StatusBarStateController.StateListener {
+ override fun onDozingChanged(isDozing: Boolean) {
+ updateListeningState()
+ }
}
override fun dump(fd: FileDescriptor, pw: PrintWriter, args: Array<out String>) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardStatusBarView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardStatusBarView.java
index 65173a2..cb332bd 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardStatusBarView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardStatusBarView.java
@@ -174,7 +174,7 @@
}
private void updateKeyguardStatusBarHeight() {
- MarginLayoutParams lp = (MarginLayoutParams) getLayoutParams();
+ MarginLayoutParams lp = (MarginLayoutParams) getLayoutParams();
lp.height = getStatusBarHeaderHeightKeyguard(mContext);
setLayoutParams(lp);
}
@@ -510,28 +510,6 @@
}
}
- void onSystemChromeAnimationStart(boolean isAnimatingOut) {
- if (isAnimatingOut) {
- mSystemIconsContainer.setVisibility(View.VISIBLE);
- mSystemIconsContainer.setAlpha(0f);
- }
- }
-
- void onSystemChromeAnimationEnd(boolean isAnimatingIn) {
- // Make sure the system icons are out of the way
- if (isAnimatingIn) {
- mSystemIconsContainer.setVisibility(View.INVISIBLE);
- mSystemIconsContainer.setAlpha(0f);
- } else {
- mSystemIconsContainer.setAlpha(1f);
- mSystemIconsContainer.setVisibility(View.VISIBLE);
- }
- }
-
- void onSystemChromeAnimationUpdate(float animatedValue) {
- mSystemIconsContainer.setAlpha(animatedValue);
- }
-
@Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {
super.onLayout(changed, l, t, r, b);
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 1df1aff..a70ba82 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardStatusBarViewController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardStatusBarViewController.java
@@ -17,8 +17,6 @@
package com.android.systemui.statusbar.phone;
import static com.android.systemui.statusbar.StatusBarState.KEYGUARD;
-import static com.android.systemui.statusbar.events.SystemStatusAnimationSchedulerKt.ANIMATING_IN;
-import static com.android.systemui.statusbar.events.SystemStatusAnimationSchedulerKt.ANIMATING_OUT;
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
@@ -47,6 +45,7 @@
import com.android.systemui.statusbar.notification.PropertyAnimator;
import com.android.systemui.statusbar.notification.stack.AnimationProperties;
import com.android.systemui.statusbar.notification.stack.StackStateAnimator;
+import com.android.systemui.statusbar.phone.fragment.StatusBarSystemEventAnimator;
import com.android.systemui.statusbar.phone.userswitcher.StatusBarUserInfoTracker;
import com.android.systemui.statusbar.phone.userswitcher.StatusBarUserSwitcherController;
import com.android.systemui.statusbar.phone.userswitcher.StatusBarUserSwitcherFeatureController;
@@ -59,7 +58,6 @@
import java.io.FileDescriptor;
import java.io.PrintWriter;
import java.util.Arrays;
-import java.util.Collections;
import java.util.List;
import javax.inject.Inject;
@@ -107,6 +105,8 @@
@Override
public void onDensityOrFontScaleChanged() {
mView.loadDimens();
+ // The animator is dependent on resources for offsets
+ mSystemEventAnimator = new StatusBarSystemEventAnimator(mView, getResources());
}
@Override
@@ -123,21 +123,16 @@
private final SystemStatusAnimationCallback mAnimationCallback =
new SystemStatusAnimationCallback() {
+ @NonNull
@Override
- public void onSystemChromeAnimationStart() {
- mView.onSystemChromeAnimationStart(
- mAnimationScheduler.getAnimationState() == ANIMATING_OUT);
+ public Animator onSystemEventAnimationFinish(boolean hasPersistentDot) {
+ return mSystemEventAnimator.onSystemEventAnimationFinish(hasPersistentDot);
}
+ @NonNull
@Override
- public void onSystemChromeAnimationEnd() {
- mView.onSystemChromeAnimationEnd(
- mAnimationScheduler.getAnimationState() == ANIMATING_IN);
- }
-
- @Override
- public void onSystemChromeAnimationUpdate(@NonNull ValueAnimator anim) {
- mView.onSystemChromeAnimationUpdate((float) anim.getAnimatedValue());
+ public Animator onSystemEventAnimationBegin() {
+ return mSystemEventAnimator.onSystemEventAnimationBegin();
}
};
@@ -232,6 +227,7 @@
private int mStatusBarState;
private boolean mDozing;
private boolean mShowingKeyguardHeadsUp;
+ private StatusBarSystemEventAnimator mSystemEventAnimator;
@Inject
public KeyguardStatusBarViewController(
@@ -292,16 +288,15 @@
);
Resources r = getResources();
- mBlockedIcons = Collections.unmodifiableList(Arrays.asList(
- r.getString(com.android.internal.R.string.status_bar_volume),
- r.getString(com.android.internal.R.string.status_bar_alarm_clock),
- r.getString(com.android.internal.R.string.status_bar_call_strength)));
+ mBlockedIcons = Arrays.asList(r.getStringArray(
+ R.array.config_keyguard_statusbar_icon_blocklist));
mNotificationsHeaderCollideDistance = r.getDimensionPixelSize(
R.dimen.header_notifications_collide_distance);
mView.setKeyguardUserAvatarEnabled(
!mFeatureController.isStatusBarUserSwitcherFeatureEnabled());
mFeatureController.addCallback(enabled -> mView.setKeyguardUserAvatarEnabled(!enabled));
+ mSystemEventAnimator = new StatusBarSystemEventAnimator(mView, r);
}
@Override
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelViewController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelViewController.java
index 1891ab0..5746ffb 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelViewController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelViewController.java
@@ -17,7 +17,6 @@
package com.android.systemui.statusbar.phone;
import static android.app.StatusBarManager.WINDOW_STATE_SHOWING;
-import static android.view.View.GONE;
import static androidx.constraintlayout.widget.ConstraintSet.END;
import static androidx.constraintlayout.widget.ConstraintSet.PARENT_ID;
@@ -144,7 +143,6 @@
import com.android.systemui.statusbar.KeyguardAffordanceView;
import com.android.systemui.statusbar.KeyguardIndicationController;
import com.android.systemui.statusbar.LockscreenShadeTransitionController;
-import com.android.systemui.statusbar.NotificationLockscreenUserManager;
import com.android.systemui.statusbar.NotificationRemoteInputManager;
import com.android.systemui.statusbar.NotificationShadeDepthController;
import com.android.systemui.statusbar.NotificationShadeWindowController;
@@ -165,17 +163,16 @@
import com.android.systemui.statusbar.notification.ViewGroupFadeHelper;
import com.android.systemui.statusbar.notification.collection.ListEntry;
import com.android.systemui.statusbar.notification.collection.NotificationEntry;
-import com.android.systemui.statusbar.notification.collection.legacy.NotificationGroupManagerLegacy;
import com.android.systemui.statusbar.notification.collection.render.ShadeViewManager;
import com.android.systemui.statusbar.notification.row.ActivatableNotificationView;
import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
import com.android.systemui.statusbar.notification.row.ExpandableView;
import com.android.systemui.statusbar.notification.stack.AmbientState;
import com.android.systemui.statusbar.notification.stack.AnimationProperties;
-import com.android.systemui.statusbar.notification.stack.MediaContainerView;
import com.android.systemui.statusbar.notification.stack.NotificationListContainer;
import com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayout;
import com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayoutController;
+import com.android.systemui.statusbar.notification.stack.NotificationStackSizeCalculator;
import com.android.systemui.statusbar.notification.stack.StackStateAnimator;
import com.android.systemui.statusbar.phone.LockscreenGestureLogger.LockscreenUiEvent;
import com.android.systemui.statusbar.phone.dagger.CentralSurfacesComponent;
@@ -312,9 +309,6 @@
private final ControlsComponent mControlsComponent;
private final NotificationRemoteInputManager mRemoteInputManager;
- // Maximum # notifications to show on Keyguard; extras will be collapsed in an overflow card.
- // If there are exactly 1 + mMaxKeyguardNotifications, then still shows all notifications
- private final int mMaxKeyguardNotifications;
private final LockscreenShadeTransitionController mLockscreenShadeTransitionController;
private final TapAgainViewController mTapAgainViewController;
private final SplitShadeHeaderController mSplitShadeHeaderController;
@@ -323,6 +317,8 @@
private boolean mShouldUseSplitNotificationShade;
// The bottom padding reserved for elements of the keyguard measuring notifications
private float mKeyguardNotificationBottomPadding;
+ // Space available for notifications.
+ private float mKeyguardNotificationAvailableSpace;
// Current max allowed keyguard notifications determined by measuring the panel
private int mMaxAllowedKeyguardNotifications;
@@ -446,8 +442,6 @@
setHeadsUpAnimatingAway(false);
updatePanelExpansionAndVisibility();
};
- // TODO (b/162832756): once migrated to the new pipeline, delete legacy group manager
- private NotificationGroupManagerLegacy mGroupManager;
private boolean mShowIconsWhenExpanded;
private int mIndicationBottomPadding;
private int mAmbientIndicationBottomPadding;
@@ -509,7 +503,6 @@
private final NotificationEntryManager mEntryManager;
private final CommandQueue mCommandQueue;
- private final NotificationLockscreenUserManager mLockscreenUserManager;
private final UserManager mUserManager;
private final MediaDataManager mMediaDataManager;
private final SysUiState mSysUiState;
@@ -651,6 +644,7 @@
mNotificationPanelUnfoldAnimationController;
private final NotificationListContainer mNotificationListContainer;
+ private final NotificationStackSizeCalculator mNotificationStackSizeCalculator;
private View.AccessibilityDelegate mAccessibilityDelegate = new View.AccessibilityDelegate() {
@Override
@@ -695,7 +689,6 @@
DynamicPrivacyController dynamicPrivacyController,
KeyguardBypassController bypassController, FalsingManager falsingManager,
FalsingCollector falsingCollector,
- NotificationLockscreenUserManager notificationLockscreenUserManager,
NotificationEntryManager notificationEntryManager,
KeyguardStateController keyguardStateController,
StatusBarStateController statusBarStateController,
@@ -721,7 +714,6 @@
KeyguardUserSwitcherComponent.Factory keyguardUserSwitcherComponentFactory,
KeyguardStatusBarViewComponent.Factory keyguardStatusBarViewComponentFactory,
LockscreenShadeTransitionController lockscreenShadeTransitionController,
- NotificationGroupManagerLegacy groupManager,
NotificationIconAreaController notificationIconAreaController,
AuthController authController,
ScrimController scrimController,
@@ -753,7 +745,8 @@
SysUiState sysUiState,
KeyguardUnlockAnimationController keyguardUnlockAnimationController,
NotificationListContainer notificationListContainer,
- PanelEventsEmitter panelEventsEmitter) {
+ PanelEventsEmitter panelEventsEmitter,
+ NotificationStackSizeCalculator notificationStackSizeCalculator) {
super(view,
falsingManager,
dozeLog,
@@ -785,9 +778,9 @@
mStatusBarKeyguardViewManager = statusBarKeyguardViewManager;
mNotificationsQSContainerController = notificationsQSContainerController;
mNotificationListContainer = notificationListContainer;
+ mNotificationStackSizeCalculator = notificationStackSizeCalculator;
mNotificationsQSContainerController.init();
mNotificationStackScrollLayoutController = notificationStackScrollLayoutController;
- mGroupManager = groupManager;
mNotificationIconAreaController = notificationIconAreaController;
mKeyguardStatusViewComponentFactory = keyguardStatusViewComponentFactory;
mKeyguardStatusBarViewComponentFactory = keyguardStatusBarViewComponentFactory;
@@ -849,7 +842,6 @@
});
mBottomAreaShadeAlphaAnimator.setDuration(160);
mBottomAreaShadeAlphaAnimator.setInterpolator(Interpolators.ALPHA_OUT);
- mLockscreenUserManager = notificationLockscreenUserManager;
mEntryManager = notificationEntryManager;
mConversationNotificationManager = conversationNotificationManager;
mAuthController = authController;
@@ -874,7 +866,6 @@
mView.getOverlay().add(new DebugDrawable());
}
- mMaxKeyguardNotifications = resources.getInteger(R.integer.keyguard_max_notification_count);
mKeyguardUnfoldTransition = unfoldComponent.map(c -> c.getKeyguardUnfoldTransition());
mNotificationPanelUnfoldAnimationController = unfoldComponent.map(
SysUIUnfoldComponent::getNotificationPanelUnfoldAnimationController);
@@ -1238,12 +1229,14 @@
if (mKeyguardShowing && !mKeyguardBypassController.getBypassEnabled()) {
mNotificationStackScrollLayoutController.setMaxDisplayedNotifications(
mMaxAllowedKeyguardNotifications);
- mNotificationStackScrollLayoutController.setKeyguardBottomPadding(
+ mNotificationStackScrollLayoutController.setKeyguardBottomPaddingForDebug(
mKeyguardNotificationBottomPadding);
+ mNotificationStackScrollLayoutController.mKeyguardNotificationAvailableSpaceForDebug(
+ mKeyguardNotificationAvailableSpace);
} else {
// no max when not on the keyguard
mNotificationStackScrollLayoutController.setMaxDisplayedNotifications(-1);
- mNotificationStackScrollLayoutController.setKeyguardBottomPadding(-1f);
+ mNotificationStackScrollLayoutController.setKeyguardBottomPaddingForDebug(-1f);
}
}
@@ -1454,127 +1447,38 @@
* @return the maximum keyguard notifications that can fit on the screen
*/
private int computeMaxKeyguardNotifications() {
- float minPadding = mClockPositionAlgorithm.getMinStackScrollerPadding();
int notificationPadding = Math.max(
1, mResources.getDimensionPixelSize(R.dimen.notification_divider_height));
- float shelfSize =
+ float topPadding = mNotificationStackScrollLayoutController.getTopPadding();
+ float shelfHeight =
mNotificationShelfController.getVisibility() == View.GONE
? 0
: mNotificationShelfController.getIntrinsicHeight() + notificationPadding;
+ // Padding to add to the bottom of the stack to keep a minimum distance from the top of
+ // the lock icon.
float lockIconPadding = 0;
if (mLockIconViewController.getTop() != 0) {
- lockIconPadding = mCentralSurfaces.getDisplayHeight() - mLockIconViewController.getTop()
- + mResources.getDimensionPixelSize(R.dimen.min_lock_icon_padding);
+ final float lockIconTopWithPadding = mLockIconViewController.getTop()
+ - mResources.getDimensionPixelSize(R.dimen.min_lock_icon_padding);
+ lockIconPadding = mNotificationStackScrollLayoutController.getBottom()
+ - lockIconTopWithPadding;
}
- float bottomPadding = Math.max(mIndicationBottomPadding, mAmbientIndicationBottomPadding);
- bottomPadding = Math.max(lockIconPadding, bottomPadding);
+ float bottomPadding = Math.max(lockIconPadding,
+ Math.max(mIndicationBottomPadding, mAmbientIndicationBottomPadding));
mKeyguardNotificationBottomPadding = bottomPadding;
float availableSpace =
mNotificationStackScrollLayoutController.getHeight()
- - minPadding
- - shelfSize
+ - topPadding
+ - shelfHeight
- bottomPadding;
+ mKeyguardNotificationAvailableSpace = availableSpace;
- int count = 0;
- ExpandableView previousView = null;
- for (int i = 0; i < mNotificationStackScrollLayoutController.getChildCount(); i++) {
- ExpandableView child = mNotificationStackScrollLayoutController.getChildAt(i);
- if (child instanceof ExpandableNotificationRow) {
- ExpandableNotificationRow row = (ExpandableNotificationRow) child;
- boolean suppressedSummary = mGroupManager != null
- && mGroupManager.isSummaryOfSuppressedGroup(row.getEntry().getSbn());
- if (suppressedSummary) {
- continue;
- }
- if (!canShowViewOnLockscreen(child)) {
- continue;
- }
- if (row.isRemoved()) {
- continue;
- }
- } else if (child instanceof MediaContainerView) {
- if (child.getVisibility() == GONE) {
- continue;
- }
- if (child.getIntrinsicHeight() == 0) {
- continue;
- }
- } else {
- continue;
- }
- availableSpace -= child.getMinHeight(true /* ignoreTemporaryStates */);
- availableSpace -= count == 0 ? 0 : notificationPadding;
- availableSpace -= mNotificationStackScrollLayoutController
- .calculateGapHeight(previousView, child, count);
- previousView = child;
- if (availableSpace >= 0
- && (mMaxKeyguardNotifications == -1 || count < mMaxKeyguardNotifications)) {
- count++;
- } else if (availableSpace > -shelfSize) {
- // if we are exactly the last view, then we can show us still!
- int childCount = mNotificationStackScrollLayoutController.getChildCount();
- for (int j = i + 1; j < childCount; j++) {
- ExpandableView view = mNotificationStackScrollLayoutController.getChildAt(j);
- if (view instanceof ExpandableNotificationRow
- && canShowViewOnLockscreen(view)) {
- return count;
- }
- }
- count++;
- return count;
- } else {
- return count;
- }
- }
- return count;
- }
-
- /**
- * Can a view be shown on the lockscreen when calculating the number of allowed notifications
- * to show?
- *
- * @param child the view in question
- * @return true if it can be shown
- */
- private boolean canShowViewOnLockscreen(ExpandableView child) {
- if (child.hasNoContentHeight()) {
- return false;
- }
- if (child instanceof ExpandableNotificationRow &&
- !canShowRowOnLockscreen((ExpandableNotificationRow) child)) {
- return false;
- } else if (child.getVisibility() == GONE) {
- // ENRs can be gone and count because their visibility is only set after
- // this calculation, but all other views should be up to date
- return false;
- }
- return true;
- }
-
- /**
- * Can a row be shown on the lockscreen when calculating the number of allowed notifications
- * to show?
- *
- * @param row the row in question
- * @return true if it can be shown
- */
- private boolean canShowRowOnLockscreen(ExpandableNotificationRow row) {
- boolean suppressedSummary =
- mGroupManager != null && mGroupManager.isSummaryOfSuppressedGroup(
- row.getEntry().getSbn());
- if (suppressedSummary) {
- return false;
- }
- if (!mLockscreenUserManager.shouldShowOnKeyguard(row.getEntry())) {
- return false;
- }
- if (row.isRemoved()) {
- return false;
- }
- return true;
+ return mNotificationStackSizeCalculator.computeMaxKeyguardNotifications(
+ mNotificationStackScrollLayoutController.getView(), availableSpace,
+ shelfHeight);
}
private void updateClock() {
@@ -4883,6 +4787,8 @@
"calculateNotificationsTopPadding()");
drawDebugInfo(canvas, mClockPositionResult.clockY, Color.GRAY,
"mClockPositionResult.clockY");
+ drawDebugInfo(canvas, (int) mLockIconViewController.getTop(), Color.GRAY,
+ "mLockIconViewController.getTop()");
mDebugPaint.setColor(Color.CYAN);
canvas.drawLine(0, mClockPositionResult.stackScrollerPadding, mView.getWidth(),
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelViewController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelViewController.java
index 24f5ff8..78edc07 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelViewController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelViewController.java
@@ -445,7 +445,7 @@
mLockscreenGestureLogger.log(LockscreenUiEvent.LOCKSCREEN_UNLOCK);
}
@Classifier.InteractionType int interactionType = vel == 0 ? GENERIC
- : vel > 0 ? QUICK_SETTINGS
+ : y - mInitialTouchY > 0 ? QUICK_SETTINGS
: (mKeyguardStateController.canDismissLockScreen()
? UNLOCK : BOUNCER_UNLOCK);
@@ -532,7 +532,7 @@
return true;
}
- @Classifier.InteractionType int interactionType = vel > 0
+ @Classifier.InteractionType int interactionType = y - mInitialTouchY > 0
? QUICK_SETTINGS : (
mKeyguardStateController.canDismissLockScreen() ? UNLOCK : BOUNCER_UNLOCK);
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 0059c1b..d7abf74 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicy.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicy.java
@@ -349,7 +349,7 @@
}
private String getManagedProfileAccessibilityString() {
- return mDevicePolicyManager.getString(
+ return mDevicePolicyManager.getResources().getString(
STATUS_BAR_WORK_ICON_ACCESSIBILITY,
() -> mResources.getString(R.string.accessibility_managed_profile));
}
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 419661b7..029a7a5 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java
@@ -41,6 +41,7 @@
import com.android.internal.colorextraction.ColorExtractor.GradientColors;
import com.android.internal.graphics.ColorUtils;
import com.android.internal.util.function.TriConsumer;
+import com.android.keyguard.BouncerPanelExpansionCalculator;
import com.android.keyguard.KeyguardUpdateMonitor;
import com.android.keyguard.KeyguardUpdateMonitorCallback;
import com.android.settingslib.Utils;
@@ -116,6 +117,15 @@
private float mTransitionToFullShadeProgress;
/**
+ * Same as {@link #mTransitionToFullShadeProgress}, but specifically for the notifications scrim
+ * on the lock screen.
+ *
+ * On split shade lock screen we want the different scrims to fade in at different times and
+ * rates.
+ */
+ private float mTransitionToLockScreenFullShadeNotificationsProgress;
+
+ /**
* If we're currently transitioning to the full shade.
*/
private boolean mTransitioningToFullShade;
@@ -574,11 +584,17 @@
* Set the amount of progress we are currently in if we're transitioning to the full shade.
* 0.0f means we're not transitioning yet, while 1 means we're all the way in the full
* shade.
+ *
+ * @param progress the progress for all scrims.
+ * @param lockScreenNotificationsProgress the progress specifically for the notifications scrim.
*/
- public void setTransitionToFullShadeProgress(float progress) {
- if (progress != mTransitionToFullShadeProgress) {
+ public void setTransitionToFullShadeProgress(float progress,
+ float lockScreenNotificationsProgress) {
+ if (progress != mTransitionToFullShadeProgress || lockScreenNotificationsProgress
+ != mTransitionToLockScreenFullShadeNotificationsProgress) {
mTransitionToFullShadeProgress = progress;
- setTransitionToFullShade(progress > 0.0f);
+ mTransitionToLockScreenFullShadeNotificationsProgress = lockScreenNotificationsProgress;
+ setTransitionToFullShade(progress > 0.0f || lockScreenNotificationsProgress > 0.0f);
applyAndDispatchState();
}
}
@@ -754,12 +770,13 @@
} else {
mNotificationsAlpha = Math.max(1.0f - getInterpolatedFraction(), mQsExpansion);
}
- if (mState == ScrimState.KEYGUARD && mTransitionToFullShadeProgress > 0.0f) {
+ if (mState == ScrimState.KEYGUARD
+ && mTransitionToLockScreenFullShadeNotificationsProgress > 0.0f) {
// Interpolate the notification alpha when transitioning!
mNotificationsAlpha = MathUtils.lerp(
mNotificationsAlpha,
getInterpolatedFraction(),
- mTransitionToFullShadeProgress);
+ mTransitionToLockScreenFullShadeNotificationsProgress);
}
mNotificationsTint = mState.getNotifTint();
mBehindTint = behindTint;
@@ -792,7 +809,15 @@
private Pair<Integer, Float> calculateBackStateForState(ScrimState state) {
// Either darken of make the scrim transparent when you
// pull down the shade
- float interpolatedFract = getInterpolatedFraction();
+ float interpolatedFract;
+
+ if (state == ScrimState.KEYGUARD) {
+ interpolatedFract = BouncerPanelExpansionCalculator
+ .getBackScrimScaledExpansion(mPanelExpansionFraction);
+ } else {
+ interpolatedFract = getInterpolatedFraction();
+ }
+
float stateBehind = mClipsQsScrim ? state.getNotifAlpha() : state.getBehindAlpha();
float behindAlpha;
int behindTint;
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 637e4be..6fe92fa 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarNotificationActivityStarter.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarNotificationActivityStarter.java
@@ -397,15 +397,25 @@
mMainThreadHandler.post(() -> {
final Runnable removeNotification = () -> {
mOnUserInteractionCallback.onDismiss(entry, REASON_CLICK, summaryToRemove);
+ if (!animate) {
+ // If we're animating, this would be invoked after the activity launch
+ // animation completes. Since we're not animating, the launch already
+ // happened synchronously, so we notify the launch is complete here after
+ // onDismiss.
+ mLaunchEventsEmitter.notifyFinishLaunchNotifActivity(entry);
+ }
};
if (mPresenter.isCollapsing()) {
- // To avoid lags we're only performing the remove
- // after the shade is collapsed
+ // To avoid lags we're only performing the remove after the shade is collapsed
mShadeController.addPostCollapseAction(removeNotification);
} else {
removeNotification.run();
}
});
+ } else if (!canBubble && !animate) {
+ // Not animating, this is the end of the launch flow (see above comment for more info).
+ mMainThreadHandler.post(
+ () -> mLaunchEventsEmitter.notifyFinishLaunchNotifActivity(entry));
}
mIsCollapsingToShowActivityOverLockscreen = false;
@@ -481,8 +491,9 @@
boolean isActivityIntent) {
mLogger.logStartNotificationIntent(entry.getKey(), intent);
try {
- Runnable onFinishAnimationCallback =
- () -> mLaunchEventsEmitter.notifyFinishLaunchNotifActivity(entry);
+ Runnable onFinishAnimationCallback = animate
+ ? () -> mLaunchEventsEmitter.notifyFinishLaunchNotifActivity(entry)
+ : null;
ActivityLaunchAnimator.Controller animationController =
new StatusBarLaunchAnimatorController(
mNotificationAnimationProvider
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 2c84219..8194957 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
@@ -20,12 +20,10 @@
import static android.app.StatusBarManager.DISABLE_ONGOING_CALL_CHIP;
import static android.app.StatusBarManager.DISABLE_SYSTEM_INFO;
-import static com.android.systemui.statusbar.events.SystemStatusAnimationSchedulerKt.ANIMATING_IN;
-import static com.android.systemui.statusbar.events.SystemStatusAnimationSchedulerKt.ANIMATING_OUT;
import static com.android.systemui.statusbar.events.SystemStatusAnimationSchedulerKt.IDLE;
import static com.android.systemui.statusbar.events.SystemStatusAnimationSchedulerKt.SHOWING_PERSISTENT_DOT;
-import android.animation.ValueAnimator;
+import android.animation.Animator;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.SuppressLint;
@@ -74,6 +72,7 @@
import com.android.systemui.util.settings.SecureSettings;
import java.util.ArrayList;
+import java.util.Arrays;
import java.util.List;
import java.util.concurrent.Executor;
@@ -136,6 +135,7 @@
}
};
private OperatorNameViewController mOperatorNameViewController;
+ private StatusBarSystemEventAnimator mSystemEventAnimator;
@SuppressLint("ValidFragment")
public CollapsedStatusBarFragment(
@@ -210,18 +210,31 @@
initEmergencyCryptkeeperText();
initOperatorName();
initNotificationIconArea();
- mAnimationScheduler.addCallback(this);
+ mSystemEventAnimator =
+ new StatusBarSystemEventAnimator(mSystemIconArea, getResources());
}
@VisibleForTesting
void updateBlockedIcons() {
mBlockedIcons.clear();
- if (mSecureSettings.getInt(Settings.Secure.STATUS_BAR_SHOW_VIBRATE_ICON, 0) == 0) {
- mBlockedIcons.add(getString(com.android.internal.R.string.status_bar_volume));
+ // Reload the blocklist from res
+ List<String> blockList = Arrays.asList(getResources().getStringArray(
+ R.array.config_collapsed_statusbar_icon_blocklist));
+ String vibrateIconSlot = getString(com.android.internal.R.string.status_bar_volume);
+ boolean showVibrateIcon =
+ mSecureSettings.getInt(Settings.Secure.STATUS_BAR_SHOW_VIBRATE_ICON, 0) == 0;
+
+ // Filter out vibrate icon from the blocklist if the setting is on
+ for (int i = 0; i < blockList.size(); i++) {
+ if (blockList.get(i).equals(vibrateIconSlot)) {
+ if (showVibrateIcon) {
+ mBlockedIcons.add(blockList.get(i));
+ }
+ } else {
+ mBlockedIcons.add(blockList.get(i));
+ }
}
- mBlockedIcons.add(getString(com.android.internal.R.string.status_bar_alarm_clock));
- mBlockedIcons.add(getString(com.android.internal.R.string.status_bar_call_strength));
mMainExecutor.execute(() -> mDarkIconManager.setBlockList(mBlockedIcons));
}
@@ -245,6 +258,7 @@
mCommandQueue.addCallback(this);
mStatusBarStateController.addCallback(this);
initOngoingCallChip();
+ mAnimationScheduler.addCallback(this);
mSecureSettings.registerContentObserver(
Settings.Secure.getUriFor(Settings.Secure.STATUS_BAR_SHOW_VIBRATE_ICON),
@@ -258,6 +272,7 @@
mCommandQueue.removeCallback(this);
mStatusBarStateController.removeCallback(this);
mOngoingCallController.removeCallback(mOngoingCallListener);
+ mAnimationScheduler.removeCallback(this);
mSecureSettings.unregisterContentObserver(mVolumeSettingObserver);
}
@@ -265,7 +280,6 @@
public void onDestroyView() {
super.onDestroyView();
mStatusBarIconController.removeIconGroup(mDarkIconManager);
- mAnimationScheduler.removeCallback(this);
if (mNetworkController.hasEmergencyCryptKeeperText()) {
mNetworkController.removeCallback(mSignalCallback);
}
@@ -576,35 +590,16 @@
disable(getContext().getDisplayId(), mDisabled1, mDisabled2, false /* animate */);
}
+ @Nullable
@Override
- public void onSystemChromeAnimationStart() {
- if (mAnimationScheduler.getAnimationState() == ANIMATING_OUT
- && !isSystemIconAreaDisabled()) {
- mSystemIconArea.setVisibility(View.VISIBLE);
- mSystemIconArea.setAlpha(0f);
- }
+ public Animator onSystemEventAnimationBegin() {
+ return mSystemEventAnimator.onSystemEventAnimationBegin();
}
+ @Nullable
@Override
- public void onSystemChromeAnimationEnd() {
- // Make sure the system icons are out of the way
- if (mAnimationScheduler.getAnimationState() == ANIMATING_IN) {
- mSystemIconArea.setVisibility(View.INVISIBLE);
- mSystemIconArea.setAlpha(0f);
- } else {
- if (isSystemIconAreaDisabled()) {
- // don't unhide
- return;
- }
-
- mSystemIconArea.setAlpha(1f);
- mSystemIconArea.setVisibility(View.VISIBLE);
- }
- }
-
- @Override
- public void onSystemChromeAnimationUpdate(@NonNull ValueAnimator animator) {
- mSystemIconArea.setAlpha((float) animator.getAnimatedValue());
+ public Animator onSystemEventAnimationFinish(boolean hasPersistentDot) {
+ return mSystemEventAnimator.onSystemEventAnimationFinish(hasPersistentDot);
}
private boolean isSystemIconAreaDisabled() {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/fragment/StatusBarSystemEventAnimator.kt b/packages/SystemUI/src/com/android/systemui/statusbar/phone/fragment/StatusBarSystemEventAnimator.kt
new file mode 100644
index 0000000..f530ec8
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/fragment/StatusBarSystemEventAnimator.kt
@@ -0,0 +1,84 @@
+/*
+ * 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.phone.fragment
+
+import android.animation.Animator
+import android.animation.AnimatorSet
+import android.animation.ValueAnimator
+import android.content.res.Resources
+import android.view.View
+import com.android.systemui.R
+import com.android.systemui.statusbar.events.STATUS_BAR_X_MOVE_IN
+import com.android.systemui.statusbar.events.STATUS_BAR_X_MOVE_OUT
+import com.android.systemui.statusbar.events.SystemStatusAnimationCallback
+
+/**
+ * Tied directly to [SystemStatusAnimationScheduler]. Any StatusBar-like thing (keyguard, collapsed
+ * status bar fragment), can just feed this an animatable view to get the default system status
+ * animation.
+ *
+ * This animator relies on resources, and should be recreated whenever resources are updated. While
+ * this class could be used directly as the animation callback, it's probably best to forward calls
+ * to it so that it can be recreated at any moment without needing to remove/add callback.
+ */
+class StatusBarSystemEventAnimator(
+ val animatedView: View,
+ resources: Resources
+) : SystemStatusAnimationCallback {
+ private val translationXIn: Int = resources.getDimensionPixelSize(
+ R.dimen.ongoing_appops_chip_animation_in_status_bar_translation_x)
+ private val translationXOut: Int = resources.getDimensionPixelSize(
+ R.dimen.ongoing_appops_chip_animation_out_status_bar_translation_x)
+
+ override fun onSystemEventAnimationBegin(): Animator {
+ val moveOut = ValueAnimator.ofFloat(0f, 1f).setDuration(383)
+ moveOut.interpolator = STATUS_BAR_X_MOVE_OUT
+ moveOut.addUpdateListener { animation: ValueAnimator ->
+ animatedView.translationX = -(translationXIn * animation.animatedValue as Float)
+ }
+ val alphaOut = ValueAnimator.ofFloat(1f, 0f).setDuration(133)
+ alphaOut.interpolator = null
+ alphaOut.addUpdateListener { animation: ValueAnimator ->
+ animatedView.alpha = animation.animatedValue as Float
+ }
+
+ val animSet = AnimatorSet()
+ animSet.playTogether(moveOut, alphaOut)
+ return animSet
+ }
+
+ override fun onSystemEventAnimationFinish(hasPersistentDot: Boolean): Animator {
+ animatedView.translationX = translationXOut.toFloat()
+ val moveIn = ValueAnimator.ofFloat(1f, 0f).setDuration(467)
+ moveIn.startDelay = 33
+ moveIn.interpolator = STATUS_BAR_X_MOVE_IN
+ moveIn.addUpdateListener { animation: ValueAnimator ->
+ animatedView.translationX = translationXOut * animation.animatedValue as Float
+ }
+ val alphaIn = ValueAnimator.ofFloat(0f, 1f).setDuration(167)
+ alphaIn.startDelay = 67
+ alphaIn.interpolator = null
+ alphaIn.addUpdateListener { animation: ValueAnimator ->
+ animatedView.alpha = animation.animatedValue as Float
+ }
+
+ val animatorSet = AnimatorSet()
+ animatorSet.playTogether(moveIn, alphaIn)
+
+ return animatorSet
+ }
+}
\ No newline at end of file
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/RemoteInputView.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/RemoteInputView.java
index 48949f92..4d6d05f 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/RemoteInputView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/RemoteInputView.java
@@ -22,8 +22,6 @@
import android.animation.AnimatorListenerAdapter;
import android.app.ActivityManager;
import android.app.Notification;
-import android.app.PendingIntent;
-import android.app.RemoteInput;
import android.content.Context;
import android.content.pm.PackageManager;
import android.content.res.ColorStateList;
@@ -75,7 +73,6 @@
import com.android.systemui.R;
import com.android.systemui.statusbar.RemoteInputController;
import com.android.systemui.statusbar.notification.collection.NotificationEntry;
-import com.android.systemui.statusbar.notification.collection.NotificationEntry.EditedSuggestionInfo;
import com.android.systemui.statusbar.notification.row.wrapper.NotificationViewWrapper;
import com.android.systemui.statusbar.notification.stack.StackStateAnimator;
import com.android.systemui.statusbar.phone.LightBarController;
@@ -111,21 +108,15 @@
private ProgressBar mProgressBar;
private ImageView mDelete;
private ImageView mDeleteBg;
- // TODO(b/193539698): remove reveal param fields, turn them into parameters where needed
- private int mRevealCx;
- private int mRevealCy;
- private int mRevealR;
private boolean mColorized;
private int mTint;
private boolean mResetting;
+ @Nullable private RevealParams mRevealParams;
// TODO(b/193539698): move these to a Controller
private RemoteInputController mController;
private final UiEventLogger mUiEventLogger;
private NotificationEntry mEntry;
- private PendingIntent mPendingIntent;
- private RemoteInput mRemoteInput;
- private RemoteInput[] mRemoteInputs;
private boolean mRemoved;
private NotificationViewWrapper mWrapper;
@@ -397,9 +388,8 @@
// During removal, we get reattached and lose focus. Not hiding in that
// case to prevent flicker.
if (!mRemoved) {
- if (animate && mRevealR > 0) {
- Animator reveal = ViewAnimationUtils.createCircularReveal(
- this, mRevealCx, mRevealCy, mRevealR, 0);
+ if (animate && mRevealParams != null && mRevealParams.radius > 0) {
+ Animator reveal = mRevealParams.createCircularHideAnimator(this);
reveal.setInterpolator(Interpolators.FAST_OUT_LINEAR_IN);
reveal.setDuration(StackStateAnimator.ANIMATION_DURATION_CLOSE_REMOTE_INPUT);
reveal.addListener(new AnimatorListenerAdapter() {
@@ -454,30 +444,12 @@
mController.removeSpinning(mEntry.getKey(), mToken);
}
- public void setPendingIntent(PendingIntent pendingIntent) {
- mPendingIntent = pendingIntent;
+ public void setHintText(CharSequence hintText) {
+ mEditText.setHint(hintText);
}
- /**
- * Sets the remote input for this view.
- *
- * @param remoteInputs The remote inputs that need to be sent to the app.
- * @param remoteInput The remote input that needs to be activated.
- * @param editedSuggestionInfo The smart reply that should be inserted in the remote input, or
- * {@code null} if the user is not editing a smart reply.
- */
- public void setRemoteInput(RemoteInput[] remoteInputs, RemoteInput remoteInput,
- @Nullable EditedSuggestionInfo editedSuggestionInfo) {
- mRemoteInputs = remoteInputs;
- mRemoteInput = remoteInput;
- mEditText.setHint(mRemoteInput.getLabel());
- mEditText.setSupportedMimeTypes(remoteInput.getAllowedDataTypes());
-
- mEntry.editedSuggestionInfo = editedSuggestionInfo;
- if (editedSuggestionInfo != null) {
- mEntry.remoteInputText = editedSuggestionInfo.originalText;
- mEntry.remoteInputAttachment = null;
- }
+ public void setSupportedMimeTypes(Collection<String> mimeTypes) {
+ mEditText.setSupportedMimeTypes(mimeTypes);
}
/** Populates the text field of the remote input with the given content. */
@@ -486,9 +458,8 @@
}
public void focusAnimated() {
- if (getVisibility() != VISIBLE) {
- Animator animator = ViewAnimationUtils.createCircularReveal(
- this, mRevealCx, mRevealCy, 0, mRevealR);
+ if (getVisibility() != VISIBLE && mRevealParams != null) {
+ Animator animator = mRevealParams.createCircularRevealAnimator(this);
animator.setDuration(StackStateAnimator.ANIMATION_DURATION_STANDARD);
animator.setInterpolator(Interpolators.LINEAR_OUT_SLOW_IN);
animator.start();
@@ -587,30 +558,12 @@
return mEditText.isFocused() && mEditText.isEnabled();
}
- // TODO(b/193539698): move this to the controller
- public void stealFocusFrom(RemoteInputView other) {
- other.close();
- setPendingIntent(other.mPendingIntent);
- setRemoteInput(other.mRemoteInputs, other.mRemoteInput, mEntry.editedSuggestionInfo);
- setRevealParameters(other.mRevealCx, other.mRevealCy, other.mRevealR);
- getController().setPendingIntent(other.mPendingIntent);
- getController().setRemoteInput(other.mRemoteInput);
- getController().setRemoteInputs(other.mRemoteInputs);
- focus();
- }
-
- public PendingIntent getPendingIntent() {
- return mPendingIntent;
- }
-
public void setRemoved() {
mRemoved = true;
}
- public void setRevealParameters(int cx, int cy, int r) {
- mRevealCx = cx;
- mRevealCy = cy;
- mRevealR = r;
+ public void setRevealParameters(@Nullable RevealParams revealParams) {
+ mRevealParams = revealParams;
}
@Override
@@ -938,4 +891,24 @@
}
}
+
+ public static class RevealParams {
+ final int centerX;
+ final int centerY;
+ final int radius;
+
+ public RevealParams(int centerX, int centerY, int radius) {
+ this.centerX = centerX;
+ this.centerY = centerY;
+ this.radius = radius;
+ }
+
+ Animator createCircularRevealAnimator(View view) {
+ return ViewAnimationUtils.createCircularReveal(view, centerX, centerY, radius, 0);
+ }
+
+ Animator createCircularHideAnimator(View view) {
+ return ViewAnimationUtils.createCircularReveal(view, centerX, centerY, 0, radius);
+ }
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/RemoteInputViewController.kt b/packages/SystemUI/src/com/android/systemui/statusbar/policy/RemoteInputViewController.kt
index ef0a5b4..f845101 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/RemoteInputViewController.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/RemoteInputViewController.kt
@@ -33,7 +33,9 @@
import com.android.systemui.statusbar.NotificationRemoteInputManager
import com.android.systemui.statusbar.RemoteInputController
import com.android.systemui.statusbar.notification.collection.NotificationEntry
+import com.android.systemui.statusbar.notification.collection.NotificationEntry.EditedSuggestionInfo
import com.android.systemui.statusbar.policy.RemoteInputView.NotificationRemoteInputEvent
+import com.android.systemui.statusbar.policy.RemoteInputView.RevealParams
import com.android.systemui.statusbar.policy.dagger.RemoteInputViewScope
import javax.inject.Inject
@@ -41,6 +43,8 @@
fun bind()
fun unbind()
+ val isActive: Boolean
+
/**
* A [NotificationRemoteInputManager.BouncerChecker] that will be used to determine if the
* device needs to be unlocked before sending the RemoteInput.
@@ -55,6 +59,14 @@
/** Other [RemoteInput]s from the notification associated with this Controller. */
var remoteInputs: Array<RemoteInput>?
+ var revealParams: RevealParams?
+
+ /**
+ * Sets the smart reply that should be inserted in the remote input, or `null` if the user is
+ * not editing a smart reply.
+ */
+ fun setEditedSuggestionInfo(info: EditedSuggestionInfo?)
+
/**
* Tries to find an action in {@param actions} that matches the current pending intent
* of this view and updates its state to that of the found action
@@ -68,6 +80,19 @@
/** Unregisters a listener previously registered via [addOnSendRemoteInputListener] */
fun removeOnSendRemoteInputListener(listener: OnSendRemoteInputListener)
+
+ fun close()
+
+ fun focus()
+
+ fun stealFocusFrom(other: RemoteInputViewController) {
+ other.close()
+ remoteInput = other.remoteInput
+ remoteInputs = other.remoteInputs
+ revealParams = other.revealParams
+ pendingIntent = other.pendingIntent
+ focus()
+ }
}
/** Listener for send events */
@@ -100,15 +125,41 @@
private var isBound = false
- override var pendingIntent: PendingIntent? = null
override var bouncerChecker: NotificationRemoteInputManager.BouncerChecker? = null
+
override var remoteInput: RemoteInput? = null
+ set(value) {
+ field = value
+ value?.takeIf { isBound }?.let {
+ view.setHintText(it.label)
+ view.setSupportedMimeTypes(it.allowedDataTypes)
+ }
+ }
+
+ override var pendingIntent: PendingIntent? = null
override var remoteInputs: Array<RemoteInput>? = null
+ override var revealParams: RevealParams? = null
+ set(value) {
+ field = value
+ if (isBound) {
+ view.setRevealParameters(value)
+ }
+ }
+
+ override val isActive: Boolean get() = view.isActive
+
override fun bind() {
if (isBound) return
isBound = true
+ // TODO: refreshUI method?
+ remoteInput?.let {
+ view.setHintText(it.label)
+ view.setSupportedMimeTypes(it.allowedDataTypes)
+ }
+ view.setRevealParameters(revealParams)
+
view.addOnEditTextFocusChangedListener(onFocusChangeListener)
view.addOnSendRemoteInputListener(onSendRemoteInputListener)
}
@@ -121,6 +172,14 @@
view.removeOnSendRemoteInputListener(onSendRemoteInputListener)
}
+ override fun setEditedSuggestionInfo(info: EditedSuggestionInfo?) {
+ entry.editedSuggestionInfo = info
+ if (info != null) {
+ entry.remoteInputText = info.originalText
+ entry.remoteInputAttachment = null
+ }
+ }
+
override fun updatePendingIntentFromActions(actions: Array<Notification.Action>?): Boolean {
actions ?: return false
val current: Intent = pendingIntent?.intent ?: return false
@@ -132,8 +191,7 @@
pendingIntent = actionIntent
remoteInput = input
remoteInputs = inputs
- view.pendingIntent = actionIntent
- view.setRemoteInput(inputs, input, null /* editedSuggestionInfo */)
+ setEditedSuggestionInfo(null)
return true
}
return false
@@ -148,6 +206,14 @@
onSendListeners.remove(listener)
}
+ override fun close() {
+ view.close()
+ }
+
+ override fun focus() {
+ view.focus()
+ }
+
private val onFocusChangeListener = View.OnFocusChangeListener { _, hasFocus ->
remoteInputQuickSettingsDisabler.setRemoteInputActive(hasFocus)
}
@@ -217,11 +283,12 @@
* @return returns intent with granted URI permissions that should be used immediately
*/
private fun prepareRemoteInput(remoteInput: RemoteInput): Intent =
- if (entry.remoteInputAttachment == null) prepareRemoteInputFromText(remoteInput)
- else prepareRemoteInputFromData(
- remoteInput,
- entry.remoteInputMimeType,
- entry.remoteInputUri)
+ if (entry.remoteInputAttachment == null)
+ prepareRemoteInputFromText(remoteInput)
+ else prepareRemoteInputFromData(
+ remoteInput,
+ entry.remoteInputMimeType,
+ entry.remoteInputUri)
private fun prepareRemoteInputFromText(remoteInput: RemoteInput): Intent {
val results = Bundle()
@@ -232,11 +299,7 @@
view.clearAttachment()
entry.remoteInputUri = null
entry.remoteInputMimeType = null
- if (entry.editedSuggestionInfo == null) {
- RemoteInput.setResultsSource(fillInIntent, RemoteInput.SOURCE_FREE_FORM_INPUT)
- } else {
- RemoteInput.setResultsSource(fillInIntent, RemoteInput.SOURCE_CHOICE)
- }
+ RemoteInput.setResultsSource(fillInIntent, remoteInputResultsSource)
return fillInIntent
}
@@ -266,11 +329,12 @@
entry.remoteInputText = fullText
// mirror prepareRemoteInputFromText for text input
- if (entry.editedSuggestionInfo == null) {
- RemoteInput.setResultsSource(fillInIntent, RemoteInput.SOURCE_FREE_FORM_INPUT)
- } else if (entry.remoteInputAttachment == null) {
- RemoteInput.setResultsSource(fillInIntent, RemoteInput.SOURCE_CHOICE)
- }
+ RemoteInput.setResultsSource(fillInIntent, remoteInputResultsSource)
return fillInIntent
}
+
+ private val remoteInputResultsSource
+ get() = entry.editedSuggestionInfo
+ ?.let { RemoteInput.SOURCE_CHOICE }
+ ?: RemoteInput.SOURCE_FREE_FORM_INPUT
}
diff --git a/packages/SystemUI/src/com/android/systemui/user/UserSwitcherActivity.kt b/packages/SystemUI/src/com/android/systemui/user/UserSwitcherActivity.kt
index c0d7925..9e9b746 100644
--- a/packages/SystemUI/src/com/android/systemui/user/UserSwitcherActivity.kt
+++ b/packages/SystemUI/src/com/android/systemui/user/UserSwitcherActivity.kt
@@ -23,7 +23,6 @@
import android.graphics.drawable.BitmapDrawable
import android.graphics.drawable.Drawable
import android.graphics.drawable.GradientDrawable
-import android.graphics.drawable.InsetDrawable
import android.graphics.drawable.LayerDrawable
import android.os.Bundle
import android.os.UserManager
@@ -149,8 +148,8 @@
}
private fun getDrawable(item: UserRecord): Drawable {
- var drawable = if (item.isCurrent && item.isGuest) {
- getDrawable(R.drawable.ic_avatar_guest_user)
+ var drawable = if (item.isGuest) {
+ getDrawable(R.drawable.ic_account_circle)
} else {
findUserIcon(item)
}
@@ -168,7 +167,7 @@
val ld = getDrawable(R.drawable.user_switcher_icon_large).mutate()
as LayerDrawable
if (item == userSwitcherController.getCurrentUserRecord()) {
- (ld.getDrawable(1) as GradientDrawable).apply {
+ (ld.findDrawableByLayerId(R.id.ring) as GradientDrawable).apply {
val stroke = resources
.getDimensionPixelSize(R.dimen.user_switcher_icon_selected_width)
val color = Utils.getColorAttrDefaultColor(
@@ -180,15 +179,7 @@
}
}
- ld.addLayer(
- InsetDrawable(
- drawable,
- resources.getDimensionPixelSize(
- R.dimen.user_switcher_icon_large_margin
- )
- )
- )
-
+ ld.setDrawableByLayerId(R.id.user_avatar, drawable)
return ld
}
diff --git a/packages/SystemUI/src/com/android/systemui/util/animation/AnimationUtil.kt b/packages/SystemUI/src/com/android/systemui/util/animation/AnimationUtil.kt
new file mode 100644
index 0000000..c0538c1
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/util/animation/AnimationUtil.kt
@@ -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.systemui.util.animation
+
+import kotlin.math.roundToLong
+
+/** A generic util class for animations in SysUI. */
+class AnimationUtil {
+ companion object {
+ /**
+ * Returns the number of milliseconds there are in [numFrames] for a 60 fps device.
+ *
+ * Note that this method can be used on any device, not just 60 fps devices. Animation
+ * lengths are typically specified in terms of number of frames for a 60 fps device, and
+ * the value "5 frames" is often more meaningful than "83ms". This method allows us to
+ * write animation code in terms of the more meaningful "5" number.
+ *
+ * @param numFrames must be >= 0.
+ */
+ fun getMsForFrames(numFrames: Int): Long {
+ if (numFrames < 0) {
+ throw IllegalArgumentException("numFrames must be >= 0")
+ }
+ return (numFrames * 1000f / 60f).roundToLong()
+ }
+ }
+}
diff --git a/packages/SystemUI/tests/src/com/android/keyguard/BouncerPanelExpansionCalculatorTest.kt b/packages/SystemUI/tests/src/com/android/keyguard/BouncerPanelExpansionCalculatorTest.kt
new file mode 100644
index 0000000..6266bf1
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/keyguard/BouncerPanelExpansionCalculatorTest.kt
@@ -0,0 +1,71 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.keyguard
+
+import android.test.suitebuilder.annotation.SmallTest
+import android.testing.AndroidTestingRunner
+import com.android.systemui.SysuiTestCase
+import com.google.common.truth.Truth.assertThat
+import org.junit.Assert.assertEquals
+import org.junit.Test
+import org.junit.runner.RunWith
+
+@RunWith(AndroidTestingRunner::class)
+@SmallTest
+class BouncerPanelExpansionCalculatorTest : SysuiTestCase() {
+ @Test
+ fun testGetHostViewScaledExpansion() {
+ assertThat(BouncerPanelExpansionCalculator.getHostViewScaledExpansion(1f))
+ .isEqualTo(1f)
+ assertThat(BouncerPanelExpansionCalculator.getHostViewScaledExpansion(0.9f))
+ .isEqualTo(1f)
+ assertThat(BouncerPanelExpansionCalculator.getHostViewScaledExpansion(0.59f))
+ .isEqualTo(0f)
+ assertThat(BouncerPanelExpansionCalculator.getHostViewScaledExpansion(0f))
+ .isEqualTo(0f)
+ assertEquals(BouncerPanelExpansionCalculator
+ .getHostViewScaledExpansion(0.8f), 2f / 3f, 0.01f)
+ }
+
+ @Test
+ fun testGetBackScrimScaledExpansion() {
+ assertThat(BouncerPanelExpansionCalculator.getBackScrimScaledExpansion(1f))
+ .isEqualTo(1f)
+ assertEquals(BouncerPanelExpansionCalculator
+ .getBackScrimScaledExpansion(0.95f), 1f / 2f, 0.01f)
+ assertThat(BouncerPanelExpansionCalculator.getBackScrimScaledExpansion(0.9f))
+ .isEqualTo(0f)
+ assertThat(BouncerPanelExpansionCalculator.getBackScrimScaledExpansion(0.5f))
+ .isEqualTo(0f)
+ assertThat(BouncerPanelExpansionCalculator.getBackScrimScaledExpansion(0f))
+ .isEqualTo(0f)
+ }
+
+ @Test
+ fun testGetKeyguardClockScaledExpansion() {
+ assertThat(BouncerPanelExpansionCalculator.getKeyguardClockScaledExpansion(1f))
+ .isEqualTo(1f)
+ assertEquals(BouncerPanelExpansionCalculator
+ .getKeyguardClockScaledExpansion(0.8f), 1f / 3f, 0.01f)
+ assertThat(BouncerPanelExpansionCalculator.getKeyguardClockScaledExpansion(0.7f))
+ .isEqualTo(0f)
+ assertThat(BouncerPanelExpansionCalculator.getBackScrimScaledExpansion(0.5f))
+ .isEqualTo(0f)
+ assertThat(BouncerPanelExpansionCalculator.getBackScrimScaledExpansion(0f))
+ .isEqualTo(0f)
+ }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/SysuiTestCase.java b/packages/SystemUI/tests/src/com/android/systemui/SysuiTestCase.java
index 7a0db1f..8c79277 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/SysuiTestCase.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/SysuiTestCase.java
@@ -208,6 +208,11 @@
}
}
+ /** Delegates to {@link android.testing.TestableResources#addOverride(int, Object)}. */
+ protected void overrideResource(int resourceId, Object value) {
+ mContext.getOrCreateTestableResources().addOverride(resourceId, value);
+ }
+
public static final class EmptyRunnable implements Runnable {
public void run() {
}
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 a49c4d7..c684b66 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/accessibility/WindowMagnificationControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/accessibility/WindowMagnificationControllerTest.java
@@ -172,11 +172,10 @@
@Test
public void enableWindowMagnification_notifySourceBoundsChanged() {
- mInstrumentation.runOnMainSync(() -> {
- mWindowMagnificationController.enableWindowMagnification(Float.NaN, Float.NaN,
- Float.NaN, /* magnificationFrameOffsetRatioX= */ 0,
- /* magnificationFrameOffsetRatioY= */ 0, null);
- });
+ mInstrumentation.runOnMainSync(
+ () -> mWindowMagnificationController.enableWindowMagnification(Float.NaN, Float.NaN,
+ Float.NaN, /* magnificationFrameOffsetRatioX= */ 0,
+ /* magnificationFrameOffsetRatioY= */ 0, null));
// Waits for the surface created
verify(mWindowMagnifierCallback, timeout(LAYOUT_CHANGE_TIMEOUT_MS)).onSourceBoundsChanged(
@@ -184,6 +183,16 @@
}
@Test
+ public void enableWindowMagnification_disabled_notifySourceBoundsChanged() {
+ enableWindowMagnification_notifySourceBoundsChanged();
+ mInstrumentation.runOnMainSync(
+ () -> mWindowMagnificationController.deleteWindowMagnification(null));
+ Mockito.reset(mWindowMagnifierCallback);
+
+ enableWindowMagnification_notifySourceBoundsChanged();
+ }
+
+ @Test
public void enableWindowMagnification_withAnimation_schedulesFrame() {
mInstrumentation.runOnMainSync(() -> {
mWindowMagnificationController.enableWindowMagnification(2.0f, 10,
diff --git a/packages/SystemUI/tests/src/com/android/systemui/biometrics/AuthRippleControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/biometrics/AuthRippleControllerTest.kt
index ec2c1de..a95da62 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/biometrics/AuthRippleControllerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/biometrics/AuthRippleControllerTest.kt
@@ -114,12 +114,13 @@
}
@Test
- fun testFingerprintTrigger_Ripple() {
+ fun testFingerprintTrigger_KeyguardVisible_Ripple() {
// GIVEN fp exists, keyguard is visible, user doesn't need strong auth
val fpsLocation = PointF(5f, 5f)
`when`(authController.fingerprintSensorLocation).thenReturn(fpsLocation)
controller.onViewAttached()
`when`(keyguardUpdateMonitor.isKeyguardVisible).thenReturn(true)
+ `when`(keyguardUpdateMonitor.isDreaming).thenReturn(false)
`when`(keyguardUpdateMonitor.userNeedsStrongAuth()).thenReturn(false)
// WHEN fingerprint authenticated
@@ -136,7 +137,30 @@
}
@Test
- fun testFingerprintTrigger_KeyguardNotVisible_NoRipple() {
+ fun testFingerprintTrigger_Dreaming_Ripple() {
+ // GIVEN fp exists, keyguard is visible, user doesn't need strong auth
+ val fpsLocation = PointF(5f, 5f)
+ `when`(authController.fingerprintSensorLocation).thenReturn(fpsLocation)
+ controller.onViewAttached()
+ `when`(keyguardUpdateMonitor.isKeyguardVisible).thenReturn(false)
+ `when`(keyguardUpdateMonitor.isDreaming).thenReturn(true)
+ `when`(keyguardUpdateMonitor.userNeedsStrongAuth()).thenReturn(false)
+
+ // WHEN fingerprint authenticated
+ val captor = ArgumentCaptor.forClass(KeyguardUpdateMonitorCallback::class.java)
+ verify(keyguardUpdateMonitor).registerCallback(captor.capture())
+ captor.value.onBiometricAuthenticated(
+ 0 /* userId */,
+ BiometricSourceType.FINGERPRINT /* type */,
+ false /* isStrongBiometric */)
+
+ // THEN update sensor location and show ripple
+ verify(rippleView).setFingerprintSensorLocation(fpsLocation, -1f)
+ verify(rippleView).startUnlockedRipple(any())
+ }
+
+ @Test
+ fun testFingerprintTrigger_KeyguardNotVisible_NotDreaming_NoRipple() {
// GIVEN fp exists & user doesn't need strong auth
val fpsLocation = PointF(5f, 5f)
`when`(authController.udfpsSensorLocation).thenReturn(fpsLocation)
@@ -145,6 +169,7 @@
// WHEN keyguard is NOT visible & fingerprint authenticated
`when`(keyguardUpdateMonitor.isKeyguardVisible).thenReturn(false)
+ `when`(keyguardUpdateMonitor.isDreaming).thenReturn(false)
val captor = ArgumentCaptor.forClass(KeyguardUpdateMonitorCallback::class.java)
verify(keyguardUpdateMonitor).registerCallback(captor.capture())
captor.value.onBiometricAuthenticated(
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 ef82c3e..fd49766 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/biometrics/UdfpsControllerOverlayTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/biometrics/UdfpsControllerOverlayTest.kt
@@ -61,6 +61,8 @@
import org.mockito.junit.MockitoJUnit
import org.mockito.Mockito.`when` as whenever
+private const val REQUEST_ID = 2L
+
@SmallTest
@RunWith(AndroidTestingRunner::class)
@RunWithLooper(setAsMainLooper = true)
@@ -119,7 +121,7 @@
statusBarStateController, panelExpansionStateManager, statusBarKeyguardViewManager,
keyguardUpdateMonitor, dialogManager, dumpManager, transitionController,
configurationController, systemClock, keyguardStateController,
- unlockedScreenOffAnimationController, sensorProps, hbmProvider, reason,
+ unlockedScreenOffAnimationController, sensorProps, hbmProvider, REQUEST_ID, reason,
controllerCallback, onTouch, activityLaunchAnimator)
block()
}
@@ -263,6 +265,12 @@
controllerOverlay.hide()
verify(udfpsView).stopIllumination()
}
+
+ @Test
+ fun matchesRequestIds() = withReason(REASON_AUTH_BP) {
+ assertThat(controllerOverlay.matchesRequestId(REQUEST_ID)).isTrue()
+ assertThat(controllerOverlay.matchesRequestId(REQUEST_ID + 1)).isFalse()
+ }
}
private class EnrollListener(
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 613931f..406ed5c 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/biometrics/UdfpsControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/biometrics/UdfpsControllerTest.java
@@ -27,6 +27,7 @@
import static org.mockito.Mockito.inOrder;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
@@ -102,6 +103,7 @@
// Use this for inputs going into SystemUI. Use UdfpsController.mUdfpsSensorId for things
// leaving SystemUI.
private static final int TEST_UDFPS_SENSOR_ID = 1;
+ private static final long TEST_REQUEST_ID = 70;
@Rule
public MockitoRule rule = MockitoJUnit.rule();
@@ -278,7 +280,7 @@
@Test
public void dozeTimeTick() throws RemoteException {
- mOverlayController.showUdfpsOverlay(TEST_UDFPS_SENSOR_ID,
+ mOverlayController.showUdfpsOverlay(TEST_REQUEST_ID, TEST_UDFPS_SENSOR_ID,
BiometricOverlayConstants.REASON_AUTH_KEYGUARD, mUdfpsOverlayControllerCallback);
mFgExecutor.runAllReady();
mUdfpsController.dozeTimeTick();
@@ -293,7 +295,7 @@
when(mUdfpsView.getAnimationViewController()).thenReturn(mUdfpsKeyguardViewController);
// GIVEN that the overlay is showing
- mOverlayController.showUdfpsOverlay(TEST_UDFPS_SENSOR_ID,
+ mOverlayController.showUdfpsOverlay(TEST_REQUEST_ID, TEST_UDFPS_SENSOR_ID,
BiometricOverlayConstants.REASON_AUTH_KEYGUARD, mUdfpsOverlayControllerCallback);
mFgExecutor.runAllReady();
@@ -316,7 +318,7 @@
when(mStatusBarStateController.isDozing()).thenReturn(true);
// GIVEN that the overlay is showing
- mOverlayController.showUdfpsOverlay(TEST_UDFPS_SENSOR_ID,
+ mOverlayController.showUdfpsOverlay(TEST_REQUEST_ID, TEST_UDFPS_SENSOR_ID,
BiometricOverlayConstants.REASON_AUTH_KEYGUARD, mUdfpsOverlayControllerCallback);
mFgExecutor.runAllReady();
@@ -339,7 +341,7 @@
when(mStatusBarStateController.isDozing()).thenReturn(false);
// GIVEN that the overlay is showing
- mOverlayController.showUdfpsOverlay(TEST_UDFPS_SENSOR_ID,
+ mOverlayController.showUdfpsOverlay(TEST_REQUEST_ID, TEST_UDFPS_SENSOR_ID,
BiometricOverlayConstants.REASON_AUTH_KEYGUARD, mUdfpsOverlayControllerCallback);
mFgExecutor.runAllReady();
@@ -362,7 +364,7 @@
(UdfpsAnimationViewController) mock(UdfpsEnrollViewController.class));
// GIVEN that the overlay is showing
- mOverlayController.showUdfpsOverlay(TEST_UDFPS_SENSOR_ID,
+ mOverlayController.showUdfpsOverlay(TEST_REQUEST_ID, TEST_UDFPS_SENSOR_ID,
BiometricOverlayConstants.REASON_ENROLL_ENROLLING, mUdfpsOverlayControllerCallback);
mFgExecutor.runAllReady();
@@ -377,25 +379,42 @@
}
@Test
- public void onActionMoveTouch_whenCanDismissLockScreen_entersDevice() throws RemoteException {
+ public void onActionMoveTouch_whenCanDismissLockScreen_entersDevice()
+ throws RemoteException {
+ onActionMoveTouch_whenCanDismissLockScreen_entersDevice(false /* stale */);
+ }
+
+ @Test
+ public void onActionMoveTouch_whenCanDismissLockScreen_entersDevice_ignoreStale()
+ throws RemoteException {
+ onActionMoveTouch_whenCanDismissLockScreen_entersDevice(true /* stale */);
+ }
+
+ public void onActionMoveTouch_whenCanDismissLockScreen_entersDevice(boolean stale)
+ throws RemoteException {
// GIVEN can dismiss lock screen and the current animation is an UdfpsKeyguardViewController
when(mKeyguardStateController.canDismissLockScreen()).thenReturn(true);
when(mUdfpsView.isWithinSensorArea(anyFloat(), anyFloat())).thenReturn(true);
when(mUdfpsView.getAnimationViewController()).thenReturn(mUdfpsKeyguardViewController);
// GIVEN that the overlay is showing
- mOverlayController.showUdfpsOverlay(TEST_UDFPS_SENSOR_ID,
+ mOverlayController.showUdfpsOverlay(TEST_REQUEST_ID, TEST_UDFPS_SENSOR_ID,
BiometricOverlayConstants.REASON_AUTH_KEYGUARD, mUdfpsOverlayControllerCallback);
mFgExecutor.runAllReady();
// WHEN ACTION_MOVE is received
verify(mUdfpsView).setOnTouchListener(mTouchListenerCaptor.capture());
MotionEvent moveEvent = MotionEvent.obtain(0, 0, MotionEvent.ACTION_MOVE, 0, 0, 0);
+ if (stale) {
+ mOverlayController.hideUdfpsOverlay(TEST_UDFPS_SENSOR_ID);
+ mFgExecutor.runAllReady();
+ }
mTouchListenerCaptor.getValue().onTouch(mUdfpsView, moveEvent);
moveEvent.recycle();
// THEN notify keyguard authenticate to dismiss the keyguard
- verify(mStatusBarKeyguardViewManager).notifyKeyguardAuthenticated(anyBoolean());
+ verify(mStatusBarKeyguardViewManager, stale ? never() : times(1))
+ .notifyKeyguardAuthenticated(anyBoolean());
}
@Test
@@ -406,7 +425,7 @@
when(mUdfpsView.getAnimationViewController()).thenReturn(mUdfpsKeyguardViewController);
// GIVEN that the overlay is showing
- mOverlayController.showUdfpsOverlay(TEST_UDFPS_SENSOR_ID,
+ mOverlayController.showUdfpsOverlay(TEST_REQUEST_ID, TEST_UDFPS_SENSOR_ID,
BiometricOverlayConstants.REASON_AUTH_KEYGUARD, mUdfpsOverlayControllerCallback);
mFgExecutor.runAllReady();
@@ -427,7 +446,7 @@
@Test
public void hideUdfpsOverlay_resetsAltAuthBouncerWhenShowing() throws RemoteException {
// GIVEN overlay was showing and the udfps bouncer is showing
- mOverlayController.showUdfpsOverlay(TEST_UDFPS_SENSOR_ID,
+ mOverlayController.showUdfpsOverlay(TEST_REQUEST_ID, TEST_UDFPS_SENSOR_ID,
BiometricOverlayConstants.REASON_AUTH_KEYGUARD, mUdfpsOverlayControllerCallback);
when(mStatusBarKeyguardViewManager.isShowingAlternateAuth()).thenReturn(true);
@@ -441,7 +460,7 @@
@Test
public void testSubscribesToOrientationChangesWhenShowingOverlay() throws Exception {
- mOverlayController.showUdfpsOverlay(TEST_UDFPS_SENSOR_ID,
+ mOverlayController.showUdfpsOverlay(TEST_REQUEST_ID, TEST_UDFPS_SENSOR_ID,
BiometricOverlayConstants.REASON_AUTH_KEYGUARD, mUdfpsOverlayControllerCallback);
mFgExecutor.runAllReady();
@@ -460,7 +479,7 @@
when(mUdfpsView.isWithinSensorArea(anyFloat(), anyFloat())).thenReturn(true);
// GIVEN that the overlay is showing
- mOverlayController.showUdfpsOverlay(TEST_UDFPS_SENSOR_ID,
+ mOverlayController.showUdfpsOverlay(TEST_REQUEST_ID, TEST_UDFPS_SENSOR_ID,
BiometricOverlayConstants.REASON_AUTH_KEYGUARD, mUdfpsOverlayControllerCallback);
mFgExecutor.runAllReady();
// WHEN ACTION_DOWN is received
@@ -472,8 +491,9 @@
mTouchListenerCaptor.getValue().onTouch(mUdfpsView, moveEvent);
moveEvent.recycle();
// THEN FingerprintManager is notified about onPointerDown
- verify(mFingerprintManager).onPointerDown(eq(mUdfpsController.mSensorProps.sensorId), eq(0),
- eq(0), eq(0f), eq(0f));
+ verify(mFingerprintManager).onPointerDown(eq(TEST_REQUEST_ID),
+ eq(mUdfpsController.mSensorProps.sensorId),
+ eq(0), eq(0), eq(0f), eq(0f));
verify(mLatencyTracker).onActionStart(eq(LatencyTracker.ACTION_UDFPS_ILLUMINATE));
// AND illumination begins
verify(mUdfpsView).startIllumination(mOnIlluminatedRunnableCaptor.capture());
@@ -481,14 +501,15 @@
// AND onIlluminatedRunnable notifies FingerprintManager about onUiReady
mOnIlluminatedRunnableCaptor.getValue().run();
InOrder inOrder = inOrder(mFingerprintManager, mLatencyTracker);
- inOrder.verify(mFingerprintManager).onUiReady(eq(mUdfpsController.mSensorProps.sensorId));
+ inOrder.verify(mFingerprintManager).onUiReady(
+ eq(TEST_REQUEST_ID), eq(mUdfpsController.mSensorProps.sensorId));
inOrder.verify(mLatencyTracker).onActionEnd(eq(LatencyTracker.ACTION_UDFPS_ILLUMINATE));
}
@Test
public void aodInterrupt() throws RemoteException {
// GIVEN that the overlay is showing and screen is on and fp is running
- mOverlayController.showUdfpsOverlay(TEST_UDFPS_SENSOR_ID,
+ mOverlayController.showUdfpsOverlay(TEST_REQUEST_ID, TEST_UDFPS_SENSOR_ID,
BiometricOverlayConstants.REASON_AUTH_KEYGUARD, mUdfpsOverlayControllerCallback);
mScreenObserver.onScreenTurnedOn();
mFgExecutor.runAllReady();
@@ -499,14 +520,15 @@
// AND onIlluminatedRunnable that notifies FingerprintManager is set
verify(mUdfpsView).startIllumination(mOnIlluminatedRunnableCaptor.capture());
mOnIlluminatedRunnableCaptor.getValue().run();
- verify(mFingerprintManager).onPointerDown(eq(mUdfpsController.mSensorProps.sensorId), eq(0),
- eq(0), eq(3f) /* minor */, eq(2f) /* major */);
+ verify(mFingerprintManager).onPointerDown(eq(TEST_REQUEST_ID),
+ eq(mUdfpsController.mSensorProps.sensorId),
+ eq(0), eq(0), eq(3f) /* minor */, eq(2f) /* major */);
}
@Test
public void cancelAodInterrupt() throws RemoteException {
// GIVEN AOD interrupt
- mOverlayController.showUdfpsOverlay(TEST_UDFPS_SENSOR_ID,
+ mOverlayController.showUdfpsOverlay(TEST_REQUEST_ID, TEST_UDFPS_SENSOR_ID,
BiometricOverlayConstants.REASON_AUTH_KEYGUARD, mUdfpsOverlayControllerCallback);
mScreenObserver.onScreenTurnedOn();
mFgExecutor.runAllReady();
@@ -522,7 +544,7 @@
@Test
public void aodInterruptTimeout() throws RemoteException {
// GIVEN AOD interrupt
- mOverlayController.showUdfpsOverlay(TEST_UDFPS_SENSOR_ID,
+ mOverlayController.showUdfpsOverlay(TEST_REQUEST_ID, TEST_UDFPS_SENSOR_ID,
BiometricOverlayConstants.REASON_AUTH_KEYGUARD, mUdfpsOverlayControllerCallback);
mScreenObserver.onScreenTurnedOn();
mFgExecutor.runAllReady();
@@ -539,7 +561,7 @@
@Test
public void aodInterruptScreenOff() throws RemoteException {
// GIVEN screen off
- mOverlayController.showUdfpsOverlay(TEST_UDFPS_SENSOR_ID,
+ mOverlayController.showUdfpsOverlay(TEST_REQUEST_ID, TEST_UDFPS_SENSOR_ID,
BiometricOverlayConstants.REASON_AUTH_KEYGUARD, mUdfpsOverlayControllerCallback);
mScreenObserver.onScreenTurnedOff();
mFgExecutor.runAllReady();
@@ -555,7 +577,7 @@
@Test
public void aodInterrupt_fingerprintNotRunning() throws RemoteException {
// GIVEN showing overlay
- mOverlayController.showUdfpsOverlay(TEST_UDFPS_SENSOR_ID,
+ mOverlayController.showUdfpsOverlay(TEST_REQUEST_ID, TEST_UDFPS_SENSOR_ID,
BiometricOverlayConstants.REASON_AUTH_KEYGUARD,
mUdfpsOverlayControllerCallback);
mScreenObserver.onScreenTurnedOn();
@@ -577,7 +599,7 @@
// GIVEN that the overlay is showing and a11y touch exploration enabled
when(mAccessibilityManager.isTouchExplorationEnabled()).thenReturn(true);
- mOverlayController.showUdfpsOverlay(TEST_UDFPS_SENSOR_ID,
+ mOverlayController.showUdfpsOverlay(TEST_REQUEST_ID, TEST_UDFPS_SENSOR_ID,
BiometricOverlayConstants.REASON_AUTH_KEYGUARD, mUdfpsOverlayControllerCallback);
mFgExecutor.runAllReady();
@@ -612,7 +634,7 @@
// GIVEN that the overlay is showing and a11y touch exploration NOT enabled
when(mAccessibilityManager.isTouchExplorationEnabled()).thenReturn(false);
- mOverlayController.showUdfpsOverlay(TEST_UDFPS_SENSOR_ID,
+ mOverlayController.showUdfpsOverlay(TEST_REQUEST_ID, TEST_UDFPS_SENSOR_ID,
BiometricOverlayConstants.REASON_AUTH_KEYGUARD, mUdfpsOverlayControllerCallback);
mFgExecutor.runAllReady();
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 badafa4..f4b378e 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/doze/DozeScreenBrightnessTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/doze/DozeScreenBrightnessTest.java
@@ -27,6 +27,7 @@
import static com.android.systemui.doze.DozeMachine.State.FINISH;
import static com.android.systemui.doze.DozeMachine.State.INITIALIZED;
import static com.android.systemui.doze.DozeMachine.State.UNINITIALIZED;
+
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotEquals;
import static org.junit.Assert.assertNotSame;
@@ -468,37 +469,39 @@
public void transitionToDoze_shouldClampBrightness_afterTimeout_clampsToDim() {
when(mWakefulnessLifecycle.getLastSleepReason()).thenReturn(
PowerManager.GO_TO_SLEEP_REASON_TIMEOUT);
- when(mDozeParameters.shouldControlUnlockedScreenOff()).thenReturn(true);
when(mDozeParameters.shouldClampToDimBrightness()).thenReturn(true);
mScreen.transitionTo(UNINITIALIZED, INITIALIZED);
- mScreen.transitionTo(INITIALIZED, DOZE);
// If we're dozing after a timeout, and playing the unlocked screen animation, we should
// stay at or below dim brightness, because the screen dims just before timeout.
assertTrue(mServiceFake.screenBrightness <= DIM_BRIGHTNESS);
+
+ // Once we transition to Doze, use the doze brightness
+ mScreen.transitionTo(INITIALIZED, DOZE);
+ assertEquals(mServiceFake.screenBrightness, DEFAULT_BRIGHTNESS);
}
@Test
public void transitionToDoze_shouldClampBrightness_notAfterTimeout_doesNotClampToDim() {
when(mWakefulnessLifecycle.getLastSleepReason()).thenReturn(
PowerManager.GO_TO_SLEEP_REASON_POWER_BUTTON);
- when(mDozeParameters.shouldControlUnlockedScreenOff()).thenReturn(true);
when(mDozeParameters.shouldClampToDimBrightness()).thenReturn(true);
mScreen.transitionTo(UNINITIALIZED, INITIALIZED);
- mScreen.transitionTo(INITIALIZED, DOZE);
// If we're playing the unlocked screen off animation after a power button press, we should
// leave the brightness alone.
assertEquals(mServiceFake.screenBrightness, DEFAULT_BRIGHTNESS);
+
+ mScreen.transitionTo(INITIALIZED, DOZE);
+ assertEquals(mServiceFake.screenBrightness, DEFAULT_BRIGHTNESS);
}
@Test
public void transitionToDoze_noClampBrightness_afterTimeout_noScreenOff_doesNotClampToDim() {
when(mWakefulnessLifecycle.getLastSleepReason()).thenReturn(
PowerManager.GO_TO_SLEEP_REASON_TIMEOUT);
- when(mDozeParameters.shouldControlUnlockedScreenOff()).thenReturn(false);
when(mDozeParameters.shouldClampToDimBrightness()).thenReturn(false);
mScreen.transitionTo(UNINITIALIZED, INITIALIZED);
@@ -514,11 +517,9 @@
PowerManager.GO_TO_SLEEP_REASON_TIMEOUT);
when(mWakefulnessLifecycle.getWakefulness()).thenReturn(
WakefulnessLifecycle.WAKEFULNESS_GOING_TO_SLEEP);
- when(mDozeParameters.shouldControlUnlockedScreenOff()).thenReturn(false);
when(mDozeParameters.shouldClampToDimBrightness()).thenReturn(false);
mScreen.transitionTo(UNINITIALIZED, INITIALIZED);
- mScreen.transitionTo(INITIALIZED, DOZE);
assertTrue(mServiceFake.screenBrightness <= DIM_BRIGHTNESS);
}
@@ -529,7 +530,6 @@
PowerManager.GO_TO_SLEEP_REASON_POWER_BUTTON);
when(mWakefulnessLifecycle.getWakefulness()).thenReturn(
WakefulnessLifecycle.WAKEFULNESS_GOING_TO_SLEEP);
- when(mDozeParameters.shouldControlUnlockedScreenOff()).thenReturn(false);
when(mDozeParameters.shouldClampToDimBrightness()).thenReturn(false);
mScreen.transitionTo(UNINITIALIZED, INITIALIZED);
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 a32ff80..a6921b4 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/dreams/DreamOverlayStatusBarViewControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/dreams/DreamOverlayStatusBarViewControllerTest.java
@@ -53,6 +53,8 @@
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
+import java.util.concurrent.Executor;
+
@SmallTest
@RunWith(AndroidTestingRunner.class)
public class DreamOverlayStatusBarViewControllerTest extends SysuiTestCase {
@@ -90,6 +92,8 @@
@Mock
ZenModeController mZenModeController;
+ private final Executor mMainExecutor = Runnable::run;
+
DreamOverlayStatusBarViewController mController;
@Before
@@ -102,6 +106,7 @@
mController = new DreamOverlayStatusBarViewController(
mView,
mResources,
+ mMainExecutor,
mConnectivityManager,
mTouchSession,
mAlarmManager,
@@ -134,7 +139,8 @@
.thenReturn(false);
when(mConnectivityManager.getNetworkCapabilities(any())).thenReturn(mNetworkCapabilities);
mController.onViewAttached();
- verify(mView).showIcon(DreamOverlayStatusBarView.STATUS_ICON_WIFI_UNAVAILABLE, true);
+ verify(mView).showIcon(
+ DreamOverlayStatusBarView.STATUS_ICON_WIFI_UNAVAILABLE, true, null);
}
@Test
@@ -143,13 +149,16 @@
.thenReturn(true);
when(mConnectivityManager.getNetworkCapabilities(any())).thenReturn(mNetworkCapabilities);
mController.onViewAttached();
- verify(mView).showIcon(DreamOverlayStatusBarView.STATUS_ICON_WIFI_UNAVAILABLE, false);
+ verify(mView).showIcon(
+ DreamOverlayStatusBarView.STATUS_ICON_WIFI_UNAVAILABLE, false, null);
}
@Test
public void testOnViewAttachedShowsWifiIconWhenNetworkCapabilitiesUnavailable() {
when(mConnectivityManager.getNetworkCapabilities(any())).thenReturn(null);
mController.onViewAttached();
+ verify(mView).showIcon(
+ DreamOverlayStatusBarView.STATUS_ICON_WIFI_UNAVAILABLE, true, null);
}
@Test
@@ -176,7 +185,8 @@
when(mSensorPrivacyController.isSensorBlocked(SensorPrivacyManager.Sensors.CAMERA))
.thenReturn(true);
mController.onViewAttached();
- verify(mView).showIcon(DreamOverlayStatusBarView.STATUS_ICON_MIC_CAMERA_DISABLED, true);
+ verify(mView).showIcon(
+ DreamOverlayStatusBarView.STATUS_ICON_MIC_CAMERA_DISABLED, true, null);
}
@Test
@@ -186,7 +196,8 @@
when(mSensorPrivacyController.isSensorBlocked(SensorPrivacyManager.Sensors.CAMERA))
.thenReturn(false);
mController.onViewAttached();
- verify(mView).showIcon(DreamOverlayStatusBarView.STATUS_ICON_MIC_CAMERA_DISABLED, false);
+ verify(mView).showIcon(
+ DreamOverlayStatusBarView.STATUS_ICON_MIC_CAMERA_DISABLED, false, null);
}
@Test
@@ -211,7 +222,8 @@
when(mZenModeController.getZen()).thenReturn(
Settings.Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS);
mController.onViewAttached();
- verify(mView).showIcon(DreamOverlayStatusBarView.STATUS_ICON_PRIORITY_MODE_ON, true);
+ verify(mView).showIcon(
+ DreamOverlayStatusBarView.STATUS_ICON_PRIORITY_MODE_ON, true, null);
}
@Test
@@ -219,7 +231,8 @@
when(mZenModeController.getZen()).thenReturn(
Settings.Global.ZEN_MODE_OFF);
mController.onViewAttached();
- verify(mView).showIcon(DreamOverlayStatusBarView.STATUS_ICON_PRIORITY_MODE_ON, false);
+ verify(mView).showIcon(
+ DreamOverlayStatusBarView.STATUS_ICON_PRIORITY_MODE_ON, false, null);
}
@Test
@@ -250,7 +263,9 @@
ArgumentCaptor.forClass(ConnectivityManager.NetworkCallback.class);
verify(mConnectivityManager).registerNetworkCallback(any(), callbackCapture.capture());
callbackCapture.getValue().onAvailable(mNetwork);
- verify(mView).showIcon(DreamOverlayStatusBarView.STATUS_ICON_WIFI_UNAVAILABLE, false);
+
+ verify(mView).showIcon(
+ DreamOverlayStatusBarView.STATUS_ICON_WIFI_UNAVAILABLE, false, null);
}
@Test
@@ -266,7 +281,9 @@
ArgumentCaptor.forClass(ConnectivityManager.NetworkCallback.class);
verify(mConnectivityManager).registerNetworkCallback(any(), callbackCapture.capture());
callbackCapture.getValue().onLost(mNetwork);
- verify(mView).showIcon(DreamOverlayStatusBarView.STATUS_ICON_WIFI_UNAVAILABLE, true);
+
+ verify(mView).showIcon(
+ DreamOverlayStatusBarView.STATUS_ICON_WIFI_UNAVAILABLE, true, null);
}
@Test
@@ -283,7 +300,9 @@
when(mNetworkCapabilities.hasTransport(NetworkCapabilities.TRANSPORT_WIFI))
.thenReturn(true);
callbackCapture.getValue().onCapabilitiesChanged(mNetwork, mNetworkCapabilities);
- verify(mView).showIcon(DreamOverlayStatusBarView.STATUS_ICON_WIFI_UNAVAILABLE, false);
+
+ verify(mView).showIcon(
+ DreamOverlayStatusBarView.STATUS_ICON_WIFI_UNAVAILABLE, false, null);
}
@Test
@@ -333,7 +352,8 @@
callbackCapture.getValue().onSensorBlockedChanged(
SensorPrivacyManager.Sensors.MICROPHONE, true);
- verify(mView).showIcon(DreamOverlayStatusBarView.STATUS_ICON_MIC_CAMERA_DISABLED, true);
+ verify(mView).showIcon(
+ DreamOverlayStatusBarView.STATUS_ICON_MIC_CAMERA_DISABLED, true, null);
}
@Test
@@ -350,7 +370,8 @@
callbackCapture.getValue().onSensorBlockedChanged(
SensorPrivacyManager.Sensors.MICROPHONE, false);
- verify(mView).showIcon(DreamOverlayStatusBarView.STATUS_ICON_MIC_CAMERA_DISABLED, false);
+ verify(mView).showIcon(
+ DreamOverlayStatusBarView.STATUS_ICON_MIC_CAMERA_DISABLED, false, null);
}
@Test
@@ -364,7 +385,8 @@
verify(mZenModeController).addCallback(callbackCapture.capture());
callbackCapture.getValue().onZenChanged(Settings.Global.ZEN_MODE_NO_INTERRUPTIONS);
- verify(mView).showIcon(DreamOverlayStatusBarView.STATUS_ICON_PRIORITY_MODE_ON, true);
+ verify(mView).showIcon(
+ DreamOverlayStatusBarView.STATUS_ICON_PRIORITY_MODE_ON, true, null);
}
@Test
@@ -373,12 +395,12 @@
.thenReturn(Settings.Global.ZEN_MODE_OFF);
mController.onViewAttached();
-
final ArgumentCaptor<ZenModeController.Callback> callbackCapture =
ArgumentCaptor.forClass(ZenModeController.Callback.class);
verify(mZenModeController).addCallback(callbackCapture.capture());
callbackCapture.getValue().onZenChanged(Settings.Global.ZEN_MODE_OFF);
- verify(mView).showIcon(DreamOverlayStatusBarView.STATUS_ICON_PRIORITY_MODE_ON, false);
+ verify(mView).showIcon(
+ DreamOverlayStatusBarView.STATUS_ICON_PRIORITY_MODE_ON, false, null);
}
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/dreams/complication/DreamClockDateComplicationTest.java b/packages/SystemUI/tests/src/com/android/systemui/dreams/complication/DreamClockDateComplicationTest.java
index b02c506..86aa14d 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/dreams/complication/DreamClockDateComplicationTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/dreams/complication/DreamClockDateComplicationTest.java
@@ -15,11 +15,16 @@
*/
package com.android.systemui.dreams.complication;
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.junit.Assert.assertEquals;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
import android.content.Context;
import android.testing.AndroidTestingRunner;
+import android.view.View;
import androidx.test.filters.SmallTest;
@@ -32,6 +37,8 @@
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
+import javax.inject.Provider;
+
@SmallTest
@RunWith(AndroidTestingRunner.class)
public class DreamClockDateComplicationTest extends SysuiTestCase {
@@ -45,9 +52,28 @@
@Mock
private DreamClockDateComplication mComplication;
+ @Mock
+ private Provider<DreamClockDateComplication.DreamClockDateViewHolder>
+ mDreamClockDateViewHolderProvider;
+
+ @Mock
+ private DreamClockDateComplication.DreamClockDateViewHolder
+ mDreamClockDateViewHolder;
+
+ @Mock
+ private ComplicationViewModel mComplicationViewModel;
+
+ @Mock
+ private View mView;
+
+ @Mock
+ private ComplicationLayoutParams mLayoutParams;
+
@Before
public void setup() {
MockitoAnnotations.initMocks(this);
+ when(mDreamClockDateViewHolderProvider.get()).thenReturn(mDreamClockDateViewHolder);
+
}
/**
@@ -63,4 +89,40 @@
registrant.start();
verify(mDreamOverlayStateController).addComplication(eq(mComplication));
}
+
+ /**
+ * Verifies {@link DreamClockDateComplication} has the required type.
+ */
+ @Test
+ public void testComplicationRequiredTypeAvailability() {
+ final DreamClockDateComplication complication =
+ new DreamClockDateComplication(mDreamClockDateViewHolderProvider);
+ assertEquals(Complication.COMPLICATION_TYPE_DATE,
+ complication.getRequiredTypeAvailability());
+ }
+
+ /**
+ * Verifies {@link DreamClockDateComplication.DreamClockDateViewHolder} is obtainable from its
+ * provider when the complication creates view.
+ */
+ @Test
+ public void testComplicationViewHolderProviderOnCreateView() {
+ final DreamClockDateComplication complication =
+ new DreamClockDateComplication(mDreamClockDateViewHolderProvider);
+ final Complication.ViewHolder viewHolder = complication.createView(mComplicationViewModel);
+ verify(mDreamClockDateViewHolderProvider).get();
+ assertThat(viewHolder).isEqualTo(mDreamClockDateViewHolder);
+ }
+
+ /**
+ * Verifies {@link DreamClockDateComplication.DreamClockDateViewHolder} has the intended view
+ * and layout parameters from constructor.
+ */
+ @Test
+ public void testComplicationViewHolderContentAccessors() {
+ final DreamClockDateComplication.DreamClockDateViewHolder viewHolder =
+ new DreamClockDateComplication.DreamClockDateViewHolder(mView, mLayoutParams);
+ assertThat(viewHolder.getView()).isEqualTo(mView);
+ assertThat(viewHolder.getLayoutParams()).isEqualTo(mLayoutParams);
+ }
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/dreams/complication/DreamClockTimeComplicationTest.java b/packages/SystemUI/tests/src/com/android/systemui/dreams/complication/DreamClockTimeComplicationTest.java
index 088b4d5..314a30b 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/dreams/complication/DreamClockTimeComplicationTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/dreams/complication/DreamClockTimeComplicationTest.java
@@ -15,11 +15,16 @@
*/
package com.android.systemui.dreams.complication;
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.junit.Assert.assertEquals;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
import android.content.Context;
import android.testing.AndroidTestingRunner;
+import android.view.View;
import androidx.test.filters.SmallTest;
@@ -32,6 +37,8 @@
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
+import javax.inject.Provider;
+
@SmallTest
@RunWith(AndroidTestingRunner.class)
public class DreamClockTimeComplicationTest extends SysuiTestCase {
@@ -45,9 +52,27 @@
@Mock
private DreamClockTimeComplication mComplication;
+ @Mock
+ private Provider<DreamClockTimeComplication.DreamClockTimeViewHolder>
+ mDreamClockTimeViewHolderProvider;
+
+ @Mock
+ private DreamClockTimeComplication.DreamClockTimeViewHolder
+ mDreamClockTimeViewHolder;
+
+ @Mock
+ private ComplicationViewModel mComplicationViewModel;
+
+ @Mock
+ private View mView;
+
+ @Mock
+ private ComplicationLayoutParams mLayoutParams;
+
@Before
public void setup() {
MockitoAnnotations.initMocks(this);
+ when(mDreamClockTimeViewHolderProvider.get()).thenReturn(mDreamClockTimeViewHolder);
}
/**
@@ -63,4 +88,40 @@
registrant.start();
verify(mDreamOverlayStateController).addComplication(eq(mComplication));
}
+
+ /**
+ * Verifies {@link DreamClockTimeComplication} has the required type.
+ */
+ @Test
+ public void testComplicationRequiredTypeAvailability() {
+ final DreamClockTimeComplication complication =
+ new DreamClockTimeComplication(mDreamClockTimeViewHolderProvider);
+ assertEquals(Complication.COMPLICATION_TYPE_TIME,
+ complication.getRequiredTypeAvailability());
+ }
+
+ /**
+ * Verifies {@link DreamClockTimeComplication.DreamClockTimeViewHolder} is obtainable from its
+ * provider when the complication creates view.
+ */
+ @Test
+ public void testComplicationViewHolderProviderOnCreateView() {
+ final DreamClockTimeComplication complication =
+ new DreamClockTimeComplication(mDreamClockTimeViewHolderProvider);
+ final Complication.ViewHolder viewHolder = complication.createView(mComplicationViewModel);
+ verify(mDreamClockTimeViewHolderProvider).get();
+ assertThat(viewHolder).isEqualTo(mDreamClockTimeViewHolder);
+ }
+
+ /**
+ * Verifies {@link DreamClockTimeComplication.DreamClockTimeViewHolder} has the intended view
+ * and layout parameters from constructor.
+ */
+ @Test
+ public void testComplicationViewHolderContentAccessors() {
+ final DreamClockTimeComplication.DreamClockTimeViewHolder viewHolder =
+ new DreamClockTimeComplication.DreamClockTimeViewHolder(mView, mLayoutParams);
+ assertThat(viewHolder.getView()).isEqualTo(mView);
+ assertThat(viewHolder.getLayoutParams()).isEqualTo(mLayoutParams);
+ }
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/MediaCarouselControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/media/MediaCarouselControllerTest.kt
index dcbe0ab..daf81bd 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/media/MediaCarouselControllerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/media/MediaCarouselControllerTest.kt
@@ -37,7 +37,6 @@
import org.mockito.Mock
import org.mockito.MockitoAnnotations
import javax.inject.Provider
-import org.mockito.Mockito.`when` as whenever
private val DATA = MediaData(
userId = -1,
@@ -83,7 +82,6 @@
@Before
fun setup() {
MockitoAnnotations.initMocks(this)
- whenever(mediaFlags.areMediaSessionActionsEnabled()).thenReturn(true)
mediaCarouselController = MediaCarouselController(
context,
mediaControlPanelFactory,
diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/MediaControlPanelTest.kt b/packages/SystemUI/tests/src/com/android/systemui/media/MediaControlPanelTest.kt
index cb68d81..90eff1a 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/media/MediaControlPanelTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/media/MediaControlPanelTest.kt
@@ -101,7 +101,6 @@
@Mock private lateinit var mediaOutputDialogFactory: MediaOutputDialogFactory
@Mock private lateinit var mediaCarouselController: MediaCarouselController
@Mock private lateinit var falsingManager: FalsingManager
- @Mock private lateinit var mediaFlags: MediaFlags
private lateinit var appIcon: ImageView
private lateinit var albumView: ImageView
private lateinit var titleText: TextView
@@ -147,7 +146,7 @@
player = MediaControlPanel(context, bgExecutor, activityStarter, broadcastSender,
mediaViewController, seekBarViewModel, Lazy { mediaDataManager },
- mediaOutputDialogFactory, mediaCarouselController, falsingManager, mediaFlags, clock)
+ mediaOutputDialogFactory, mediaCarouselController, falsingManager, clock)
whenever(seekBarViewModel.progress).thenReturn(seekBarData)
// Set up mock views for the players
@@ -215,9 +214,6 @@
device = device,
active = true,
resumeAction = null)
-
- whenever(mediaFlags.areMediaSessionActionsEnabled()).thenReturn(false)
- whenever(mediaFlags.useMediaSessionLayout()).thenReturn(false)
}
/**
@@ -295,9 +291,6 @@
@Test
fun bindSemanticActionsOldLayout() {
- whenever(mediaFlags.areMediaSessionActionsEnabled()).thenReturn(true)
- whenever(mediaFlags.useMediaSessionLayout()).thenReturn(false)
-
val icon = Icon.createWithResource(context, android.R.drawable.ic_media_play)
val semanticActions = MediaButton(
playOrPause = MediaAction(icon, Runnable {}, "play"),
@@ -332,9 +325,6 @@
@Test
fun bindSemanticActionsNewLayout() {
- whenever(mediaFlags.areMediaSessionActionsEnabled()).thenReturn(true)
- whenever(mediaFlags.useMediaSessionLayout()).thenReturn(true)
-
val icon = Icon.createWithResource(context, android.R.drawable.ic_media_play)
val semanticActions = MediaButton(
playOrPause = MediaAction(icon, Runnable {}, "play"),
@@ -381,9 +371,6 @@
@Test
fun bindNotificationActionsNewLayout() {
- whenever(mediaFlags.areMediaSessionActionsEnabled()).thenReturn(true)
- whenever(mediaFlags.useMediaSessionLayout()).thenReturn(true)
-
val icon = Icon.createWithResource(context, android.R.drawable.ic_media_play)
val actions = listOf(
MediaAction(icon, Runnable {}, "previous"),
diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/MediaDataManagerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/media/MediaDataManagerTest.kt
index 925ae30..066f49a 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/media/MediaDataManagerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/media/MediaDataManagerTest.kt
@@ -26,6 +26,7 @@
import com.android.systemui.statusbar.SbnBuilder
import com.android.systemui.tuner.TunerService
import com.android.systemui.util.concurrency.FakeExecutor
+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.time.FakeSystemClock
@@ -167,7 +168,7 @@
whenever(mediaSmartspaceTarget.featureType).thenReturn(SmartspaceTarget.FEATURE_MEDIA)
whenever(mediaSmartspaceTarget.iconGrid).thenReturn(listOf(mediaRecommendationItem))
whenever(mediaSmartspaceTarget.creationTimeMillis).thenReturn(1234L)
- whenever(mediaFlags.areMediaSessionActionsEnabled()).thenReturn(false)
+ whenever(mediaFlags.areMediaSessionActionsEnabled(any(), any())).thenReturn(false)
}
@After
@@ -594,7 +595,7 @@
@Test
fun testPlaybackActions_noState_usesNotification() {
val desc = "Notification Action"
- whenever(mediaFlags.areMediaSessionActionsEnabled()).thenReturn(true)
+ whenever(mediaFlags.areMediaSessionActionsEnabled(any(), any())).thenReturn(true)
whenever(controller.playbackState).thenReturn(null)
val notifWithAction = SbnBuilder().run {
@@ -621,7 +622,7 @@
@Test
fun testPlaybackActions_hasPrevNext() {
val customDesc = arrayOf("custom 1", "custom 2", "custom 3", "custom 4")
- whenever(mediaFlags.areMediaSessionActionsEnabled()).thenReturn(true)
+ whenever(mediaFlags.areMediaSessionActionsEnabled(any(), any())).thenReturn(true)
val stateActions = PlaybackState.ACTION_PLAY or
PlaybackState.ACTION_SKIP_TO_PREVIOUS or
PlaybackState.ACTION_SKIP_TO_NEXT
@@ -669,7 +670,7 @@
@Test
fun testPlaybackActions_noPrevNext_usesCustom() {
val customDesc = arrayOf("custom 1", "custom 2", "custom 3", "custom 4", "custom 5")
- whenever(mediaFlags.areMediaSessionActionsEnabled()).thenReturn(true)
+ whenever(mediaFlags.areMediaSessionActionsEnabled(any(), any())).thenReturn(true)
val stateActions = PlaybackState.ACTION_PLAY
val stateBuilder = PlaybackState.Builder()
.setActions(stateActions)
@@ -707,7 +708,7 @@
@Test
fun testPlaybackActions_reservedSpace() {
val customDesc = arrayOf("custom 1", "custom 2", "custom 3", "custom 4")
- whenever(mediaFlags.areMediaSessionActionsEnabled()).thenReturn(true)
+ whenever(mediaFlags.areMediaSessionActionsEnabled(any(), any())).thenReturn(true)
val stateActions = PlaybackState.ACTION_PLAY
val stateBuilder = PlaybackState.Builder()
.setActions(stateActions)
diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/MediaHierarchyManagerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/media/MediaHierarchyManagerTest.kt
index 8e201b5..203eb47 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/media/MediaHierarchyManagerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/media/MediaHierarchyManagerTest.kt
@@ -223,6 +223,18 @@
}
@Test
+ fun calculateTransformationType_onLockSplitShade_goingToFullShade_mediaInvisible_returnsFade() {
+ enableSplitShade()
+ goToLockscreen()
+ expandQS()
+ whenever(lockHost.visible).thenReturn(false)
+ mediaHiearchyManager.setTransitionToFullShadeAmount(10000f)
+
+ val transformType = mediaHiearchyManager.calculateTransformationType()
+ assertThat(transformType).isEqualTo(MediaHierarchyManager.TRANSFORMATION_TYPE_FADE)
+ }
+
+ @Test
fun calculateTransformationType_onLockShade_inSplitShade_notExpanding_returnsFade() {
enableSplitShade()
goToLockscreen()
diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/taptotransfer/common/MediaTttChipControllerCommonTest.kt b/packages/SystemUI/tests/src/com/android/systemui/media/taptotransfer/common/MediaTttChipControllerCommonTest.kt
index ccce577..b9a69bb 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/media/taptotransfer/common/MediaTttChipControllerCommonTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/media/taptotransfer/common/MediaTttChipControllerCommonTest.kt
@@ -81,6 +81,9 @@
whenever(packageManager.getApplicationIcon(PACKAGE_NAME)).thenReturn(appIconFromPackageName)
whenever(applicationInfo.loadLabel(packageManager)).thenReturn(APP_NAME)
whenever(packageManager.getApplicationInfo(
+ any(), any<PackageManager.ApplicationInfoFlags>()
+ )).thenThrow(PackageManager.NameNotFoundException())
+ whenever(packageManager.getApplicationInfo(
eq(PACKAGE_NAME), any<PackageManager.ApplicationInfoFlags>()
)).thenReturn(applicationInfo)
context.setMockPackageManager(packageManager)
@@ -191,6 +194,28 @@
}
@Test
+ fun setIcon_nullAppIconDrawableAndNullPackageName_stillHasIcon() {
+ controllerCommon.displayChip(getState())
+ val chipView = getChipView()
+
+ controllerCommon.setIcon(chipView, appPackageName = null, appIconDrawableOverride = null)
+
+ assertThat(chipView.getAppIconView().drawable).isNotNull()
+ }
+
+ @Test
+ fun setIcon_nullAppIconDrawableAndInvalidPackageName_stillHasIcon() {
+ controllerCommon.displayChip(getState())
+ val chipView = getChipView()
+
+ controllerCommon.setIcon(
+ chipView, appPackageName = "fakePackageName", appIconDrawableOverride = null
+ )
+
+ assertThat(chipView.getAppIconView().drawable).isNotNull()
+ }
+
+ @Test
fun setIcon_nullAppIconDrawable_iconIsFromPackageName() {
controllerCommon.displayChip(getState())
val chipView = getChipView()
@@ -201,7 +226,7 @@
}
@Test
- fun displayChip_hasAppIconDrawable_iconIsDrawable() {
+ fun setIcon_hasAppIconDrawable_iconIsDrawable() {
controllerCommon.displayChip(getState())
val chipView = getChipView()
@@ -212,7 +237,29 @@
}
@Test
- fun displayChip_nullAppName_iconContentDescriptionIsFromPackageName() {
+ fun setIcon_nullAppNameAndNullPackageName_stillHasContentDescription() {
+ controllerCommon.displayChip(getState())
+ val chipView = getChipView()
+
+ controllerCommon.setIcon(chipView, appPackageName = null, appNameOverride = null)
+
+ assertThat(chipView.getAppIconView().contentDescription.toString()).isNotEmpty()
+ }
+
+ @Test
+ fun setIcon_nullAppNameAndInvalidPackageName_stillHasContentDescription() {
+ controllerCommon.displayChip(getState())
+ val chipView = getChipView()
+
+ controllerCommon.setIcon(
+ chipView, appPackageName = "fakePackageName", appNameOverride = null
+ )
+
+ assertThat(chipView.getAppIconView().contentDescription.toString()).isNotEmpty()
+ }
+
+ @Test
+ fun setIcon_nullAppName_iconContentDescriptionIsFromPackageName() {
controllerCommon.displayChip(getState())
val chipView = getChipView()
@@ -222,7 +269,7 @@
}
@Test
- fun displayChip_hasAppName_iconContentDescriptionIsAppNameOverride() {
+ fun setIcon_hasAppName_iconContentDescriptionIsAppNameOverride() {
controllerCommon.displayChip(getState())
val chipView = getChipView()
@@ -233,6 +280,21 @@
}
@Test
+ fun setIcon_iconSizeMatchesGetIconSize() {
+ controllerCommon.displayChip(getState())
+ val chipView = getChipView()
+
+ controllerCommon.setIcon(chipView, PACKAGE_NAME)
+ chipView.measure(
+ View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED),
+ View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED)
+ )
+
+ assertThat(chipView.getAppIconView().measuredWidth).isEqualTo(ICON_SIZE)
+ assertThat(chipView.getAppIconView().measuredHeight).isEqualTo(ICON_SIZE)
+ }
+
+ @Test
fun tapGestureDetected_outsideViewBounds_viewHidden() {
controllerCommon.displayChip(getState())
whenever(viewUtil.touchIsWithinView(any(), any(), any())).thenReturn(false)
@@ -297,6 +359,8 @@
override fun updateChipView(chipInfo: ChipInfo, currentChipView: ViewGroup) {
}
+
+ override fun getIconSize(isAppIcon: Boolean): Int? = ICON_SIZE
}
inner class ChipInfo : ChipInfoCommon {
@@ -307,3 +371,4 @@
private const val PACKAGE_NAME = "com.android.systemui"
private const val APP_NAME = "Fake App Name"
private const val TIMEOUT_MS = 10000L
+private const val ICON_SIZE = 47
\ No newline at end of file
diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/taptotransfer/receiver/MediaTttChipControllerReceiverTest.kt b/packages/SystemUI/tests/src/com/android/systemui/media/taptotransfer/receiver/MediaTttChipControllerReceiverTest.kt
index 355d3fe..067607f 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/media/taptotransfer/receiver/MediaTttChipControllerReceiverTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/media/taptotransfer/receiver/MediaTttChipControllerReceiverTest.kt
@@ -174,12 +174,47 @@
verify(logger).logStateChange(any(), any())
}
+ @Test
+ fun setIcon_isAppIcon_usesAppIconSize() {
+ controllerReceiver.displayChip(getChipReceiverInfo())
+ val chipView = getChipView()
+
+ controllerReceiver.setIcon(chipView, PACKAGE_NAME)
+ chipView.measure(
+ View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED),
+ View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED)
+ )
+
+ val expectedSize = controllerReceiver.getIconSize(isAppIcon = true)
+ assertThat(chipView.getAppIconView().measuredWidth).isEqualTo(expectedSize)
+ assertThat(chipView.getAppIconView().measuredHeight).isEqualTo(expectedSize)
+ }
+
+ @Test
+ fun setIcon_notAppIcon_usesGenericIconSize() {
+ controllerReceiver.displayChip(getChipReceiverInfo())
+ val chipView = getChipView()
+
+ controllerReceiver.setIcon(chipView, appPackageName = null)
+ chipView.measure(
+ View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED),
+ View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED)
+ )
+
+ val expectedSize = controllerReceiver.getIconSize(isAppIcon = false)
+ assertThat(chipView.getAppIconView().measuredWidth).isEqualTo(expectedSize)
+ assertThat(chipView.getAppIconView().measuredHeight).isEqualTo(expectedSize)
+ }
+
private fun getChipView(): ViewGroup {
val viewCaptor = ArgumentCaptor.forClass(View::class.java)
verify(windowManager).addView(viewCaptor.capture(), any())
return viewCaptor.value as ViewGroup
}
+ private fun getChipReceiverInfo(): ChipReceiverInfo =
+ ChipReceiverInfo(routeInfo, null, null)
+
private fun ViewGroup.getAppIconView() = this.requireViewById<ImageView>(R.id.app_icon)
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/privacy/PrivacyDialogControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/privacy/PrivacyDialogControllerTest.kt
index 3508226..38b448f 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/privacy/PrivacyDialogControllerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/privacy/PrivacyDialogControllerTest.kt
@@ -19,8 +19,11 @@
import android.app.ActivityManager
import android.content.Context
import android.content.Intent
+import android.content.pm.ActivityInfo
import android.content.pm.ApplicationInfo
import android.content.pm.PackageManager
+import android.content.pm.PackageManager.ResolveInfoFlags
+import android.content.pm.ResolveInfo
import android.content.pm.UserInfo
import android.os.Process.SYSTEM_UID
import android.os.UserHandle
@@ -648,6 +651,77 @@
}
}
+ @Test
+ fun testCorrectIntentSubAttribution() {
+ val usage = createMockPermGroupUsage(
+ attributionTag = TEST_ATTRIBUTION_TAG,
+ attributionLabel = "TEST_LABEL"
+ )
+
+ val activityInfo = createMockActivityInfo()
+ val resolveInfo = createMockResolveInfo(activityInfo)
+ `when`(permissionManager.getIndicatorAppOpUsageData(anyBoolean())).thenReturn(listOf(usage))
+ `when`(packageManager.resolveActivity(any(), any<ResolveInfoFlags>()))
+ .thenAnswer { resolveInfo }
+ controller.showDialog(context)
+ exhaustExecutors()
+
+ dialogProvider.list?.let { list ->
+ val navigationIntent = list.get(0).navigationIntent!!
+ assertThat(navigationIntent.action).isEqualTo(Intent.ACTION_MANAGE_PERMISSION_USAGE)
+ assertThat(navigationIntent.getStringExtra(Intent.EXTRA_PERMISSION_GROUP_NAME))
+ .isEqualTo(PERM_CAMERA)
+ assertThat(navigationIntent.getStringArrayExtra(Intent.EXTRA_ATTRIBUTION_TAGS))
+ .isEqualTo(arrayOf(TEST_ATTRIBUTION_TAG.toString()))
+ assertThat(navigationIntent.getBooleanExtra(Intent.EXTRA_SHOWING_ATTRIBUTION, false))
+ .isTrue()
+ }
+ }
+
+ @Test
+ fun testDefaultIntentOnMissingAttributionLabel() {
+ val usage = createMockPermGroupUsage(
+ attributionTag = TEST_ATTRIBUTION_TAG
+ )
+
+ val activityInfo = createMockActivityInfo()
+ val resolveInfo = createMockResolveInfo(activityInfo)
+ `when`(permissionManager.getIndicatorAppOpUsageData(anyBoolean())).thenReturn(listOf(usage))
+ `when`(packageManager.resolveActivity(any(), any<ResolveInfoFlags>()))
+ .thenAnswer { resolveInfo }
+ controller.showDialog(context)
+ exhaustExecutors()
+
+ dialogProvider.list?.let { list ->
+ assertThat(isIntentEqual(list.get(0).navigationIntent!!,
+ controller.getDefaultManageAppPermissionsIntent(TEST_PACKAGE_NAME, USER_ID)))
+ .isTrue()
+ }
+ }
+
+ @Test
+ fun testDefaultIntentOnIncorrectPermission() {
+ val usage = createMockPermGroupUsage(
+ attributionTag = TEST_ATTRIBUTION_TAG
+ )
+
+ val activityInfo = createMockActivityInfo(
+ permission = "INCORRECT_PERMISSION"
+ )
+ val resolveInfo = createMockResolveInfo(activityInfo)
+ `when`(permissionManager.getIndicatorAppOpUsageData(anyBoolean())).thenReturn(listOf(usage))
+ `when`(packageManager.resolveActivity(any(), any<ResolveInfoFlags>()))
+ .thenAnswer { resolveInfo }
+ controller.showDialog(context)
+ exhaustExecutors()
+
+ dialogProvider.list?.let { list ->
+ assertThat(isIntentEqual(list.get(0).navigationIntent!!,
+ controller.getDefaultManageAppPermissionsIntent(TEST_PACKAGE_NAME, USER_ID)))
+ .isTrue()
+ }
+ }
+
private fun exhaustExecutors() {
FakeExecutor.exhaustExecutors(backgroundExecutor, uiExecutor)
}
@@ -680,6 +754,24 @@
return user * UserHandle.PER_USER_RANGE + nextUid++
}
+ private fun createMockResolveInfo(
+ activityInfo: ActivityInfo? = null
+ ): ResolveInfo {
+ val resolveInfo = mock(ResolveInfo::class.java)
+ resolveInfo.activityInfo = activityInfo
+ return resolveInfo
+ }
+
+ private fun createMockActivityInfo(
+ permission: String = android.Manifest.permission.START_VIEW_PERMISSION_USAGE,
+ className: String = "TEST_CLASS_NAME"
+ ): ActivityInfo {
+ val activityInfo = mock(ActivityInfo::class.java)
+ activityInfo.permission = permission
+ activityInfo.name = className
+ return activityInfo
+ }
+
private fun createMockPermGroupUsage(
packageName: String = TEST_PACKAGE_NAME,
uid: Int = generateUidForUser(USER_ID),
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/dialog/InternetAdapterTest.java b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/dialog/InternetAdapterTest.java
index d3bb241..f306fd6 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/dialog/InternetAdapterTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/dialog/InternetAdapterTest.java
@@ -4,14 +4,19 @@
import static com.google.common.truth.Truth.assertThat;
+import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyBoolean;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.anyString;
+import static org.mockito.Mockito.doNothing;
+import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.reset;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
+import android.content.Context;
import android.graphics.drawable.Drawable;
import android.testing.AndroidTestingRunner;
import android.testing.TestableResources;
@@ -30,6 +35,7 @@
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
+import org.mockito.Spy;
import org.mockito.junit.MockitoJUnit;
import org.mockito.junit.MockitoRule;
@@ -40,6 +46,7 @@
@RunWith(AndroidTestingRunner.class)
public class InternetAdapterTest extends SysuiTestCase {
+ private static final String WIFI_KEY = "Wi-Fi_Key";
private static final String WIFI_TITLE = "Wi-Fi Title";
private static final String WIFI_SUMMARY = "Wi-Fi Summary";
private static final int GEAR_ICON_RES_ID = R.drawable.ic_settings_24dp;
@@ -47,6 +54,8 @@
@Rule
public MockitoRule mRule = MockitoJUnit.rule();
+ @Spy
+ private Context mSpyContext = mContext;
@Mock
private WifiEntry mInternetWifiEntry;
@@ -74,6 +83,7 @@
when(mInternetWifiEntry.getSummary(false)).thenReturn(WIFI_SUMMARY);
when(mInternetWifiEntry.isDefaultNetwork()).thenReturn(true);
when(mInternetWifiEntry.hasInternetAccess()).thenReturn(true);
+ when(mWifiEntry.getKey()).thenReturn(WIFI_KEY);
when(mWifiEntry.getTitle()).thenReturn(WIFI_TITLE);
when(mWifiEntry.getSummary(false)).thenReturn(WIFI_SUMMARY);
@@ -197,6 +207,66 @@
}
@Test
+ public void viewHolderShouldEnabled_wifiCanConnect_returnTrue() {
+ when(mWifiEntry.canConnect()).thenReturn(true);
+
+ assertThat(mViewHolder.shouldEnabled(mWifiEntry)).isTrue();
+ }
+
+ @Test
+ public void viewHolderShouldEnabled_wifiCanNotConnect_returnFalse() {
+ when(mWifiEntry.canConnect()).thenReturn(false);
+
+ assertThat(mViewHolder.shouldEnabled(mWifiEntry)).isFalse();
+ }
+
+ @Test
+ public void viewHolderShouldEnabled_wifiCanNotConnectButCanDisconnect_returnTrue() {
+ when(mWifiEntry.canConnect()).thenReturn(false);
+ when(mWifiEntry.canConnect()).thenReturn(true);
+
+ assertThat(mViewHolder.shouldEnabled(mWifiEntry)).isTrue();
+ }
+
+ @Test
+ public void viewHolderShouldEnabled_wifiCanNotConnectButIsSaved_returnTrue() {
+ when(mWifiEntry.canConnect()).thenReturn(false);
+ when(mWifiEntry.isSaved()).thenReturn(true);
+
+ assertThat(mViewHolder.shouldEnabled(mWifiEntry)).isTrue();
+ }
+
+ @Test
+ public void viewHolderOnWifiClick_wifiShouldEditBeforeConnect_startActivity() {
+ when(mWifiEntry.shouldEditBeforeConnect()).thenReturn(true);
+ mViewHolder = mInternetAdapter.onCreateViewHolder(new LinearLayout(mSpyContext), 0);
+ doNothing().when(mSpyContext).startActivity(any());
+
+ mViewHolder.onWifiClick(mWifiEntry, mock(View.class));
+
+ verify(mSpyContext).startActivity(any());
+ }
+
+ @Test
+ public void viewHolderOnWifiClick_wifiCanConnect_connectWifi() {
+ when(mWifiEntry.canConnect()).thenReturn(true);
+
+ mViewHolder.onWifiClick(mWifiEntry, mock(View.class));
+
+ verify(mInternetDialogController).connect(mWifiEntry);
+ }
+
+ @Test
+ public void viewHolderOnWifiClick_wifiCanNotConnectButIsSaved_launchWifiDetailsSetting() {
+ when(mWifiEntry.canConnect()).thenReturn(false);
+ when(mWifiEntry.isSaved()).thenReturn(true);
+
+ mViewHolder.onWifiClick(mWifiEntry, mock(View.class));
+
+ verify(mInternetDialogController).launchWifiDetailsSetting(anyString(), any());
+ }
+
+ @Test
public void viewHolderUpdateEndIcon_wifiConnected_updateGearIcon() {
mTestableResources.addOverride(GEAR_ICON_RES_ID, mGearIcon);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/dialog/InternetDialogControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/dialog/InternetDialogControllerTest.java
index a2959e2..633a9c3 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/dialog/InternetDialogControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/dialog/InternetDialogControllerTest.java
@@ -385,18 +385,16 @@
}
@Test
- public void launchWifiNetworkDetailsSetting_withNoWifiEntryKey_doNothing() {
- mInternetDialogController.launchWifiNetworkDetailsSetting(null /* key */,
- mDialogLaunchView);
+ public void launchWifiDetailsSetting_withNoWifiEntryKey_doNothing() {
+ mInternetDialogController.launchWifiDetailsSetting(null /* key */, mDialogLaunchView);
verify(mActivityStarter, never())
.postStartActivityDismissingKeyguard(any(Intent.class), anyInt());
}
@Test
- public void launchWifiNetworkDetailsSetting_withWifiEntryKey_startActivity() {
- mInternetDialogController.launchWifiNetworkDetailsSetting("wifi_entry_key",
- mDialogLaunchView);
+ public void launchWifiDetailsSetting_withWifiEntryKey_startActivity() {
+ mInternetDialogController.launchWifiDetailsSetting("wifi_entry_key", mDialogLaunchView);
verify(mActivityStarter).postStartActivityDismissingKeyguard(any(Intent.class), anyInt(),
any());
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/KeyguardIndicationControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/KeyguardIndicationControllerTest.java
index 3c1a73e..a2a02cd 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/KeyguardIndicationControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/KeyguardIndicationControllerTest.java
@@ -51,6 +51,7 @@
import android.app.IActivityManager;
import android.app.Instrumentation;
import android.app.admin.DevicePolicyManager;
+import android.app.admin.DevicePolicyResourcesManager;
import android.app.trust.TrustManager;
import android.content.BroadcastReceiver;
import android.content.ComponentName;
@@ -126,6 +127,8 @@
@Mock
private DevicePolicyManager mDevicePolicyManager;
@Mock
+ private DevicePolicyResourcesManager mDevicePolicyResourcesManager;
+ @Mock
private ViewGroup mIndicationArea;
@Mock
private KeyguardStateController mKeyguardStateController;
@@ -210,12 +213,14 @@
.thenReturn(mIndicationAreaBottom);
when(mIndicationArea.findViewById(R.id.keyguard_indication_text)).thenReturn(mTextView);
+ when(mDevicePolicyManager.getResources()).thenReturn(mDevicePolicyResourcesManager);
when(mDevicePolicyManager.getDeviceOwnerComponentOnAnyUser())
.thenReturn(DEVICE_OWNER_COMPONENT);
when(mDevicePolicyManager.getDeviceOwnerType(DEVICE_OWNER_COMPONENT))
.thenReturn(DEVICE_OWNER_TYPE_DEFAULT);
- when(mDevicePolicyManager.getString(anyString(), any())).thenReturn(mDisclosureGeneric);
- when(mDevicePolicyManager.getString(anyString(), any(), anyString()))
+ when(mDevicePolicyResourcesManager.getString(anyString(), any()))
+ .thenReturn(mDisclosureGeneric);
+ when(mDevicePolicyResourcesManager.getString(anyString(), any(), anyString()))
.thenReturn(mDisclosureWithOrganization);
mWakeLock = new WakeLockFake();
@@ -226,6 +231,10 @@
@After
public void tearDown() throws Exception {
mTextView.setAnimationsEnabled(true);
+ if (mController != null) {
+ mController.destroy();
+ mController = null;
+ }
}
private void createController() {
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/LockscreenShadeTransitionControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/LockscreenShadeTransitionControllerTest.kt
index 64a0a23..1d2a0ca 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/LockscreenShadeTransitionControllerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/LockscreenShadeTransitionControllerTest.kt
@@ -1,5 +1,6 @@
package com.android.systemui.statusbar
+import org.mockito.Mockito.`when` as whenever
import android.test.suitebuilder.annotation.SmallTest
import android.testing.AndroidTestingRunner
import android.testing.TestableLooper
@@ -18,11 +19,11 @@
import com.android.systemui.statusbar.notification.stack.AmbientState
import com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayout
import com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayoutController
+import com.android.systemui.statusbar.phone.CentralSurfaces
import com.android.systemui.statusbar.phone.KeyguardBypassController
import com.android.systemui.statusbar.phone.LSShadeTransitionLogger
import com.android.systemui.statusbar.phone.NotificationPanelViewController
import com.android.systemui.statusbar.phone.ScrimController
-import com.android.systemui.statusbar.phone.CentralSurfaces
import com.android.systemui.statusbar.policy.FakeConfigurationController
import org.junit.After
import org.junit.Assert.assertFalse
@@ -37,14 +38,13 @@
import org.mockito.ArgumentMatchers.anyFloat
import org.mockito.ArgumentMatchers.anyInt
import org.mockito.ArgumentMatchers.anyLong
+import org.mockito.ArgumentMatchers.eq
import org.mockito.Mock
import org.mockito.Mockito
import org.mockito.Mockito.clearInvocations
import org.mockito.Mockito.never
import org.mockito.Mockito.verify
import org.mockito.junit.MockitoJUnit
-import org.mockito.Mockito.`when` as whenever
-import org.mockito.ArgumentMatchers.eq
private fun <T> anyObject(): T {
return Mockito.anyObject<T>()
@@ -231,7 +231,7 @@
transitionController.dragDownAmount = 10f
verify(nsslController, never()).setTransitionToFullShadeAmount(anyFloat(), anyFloat())
verify(mediaHierarchyManager, never()).setTransitionToFullShadeAmount(anyFloat())
- verify(scrimController, never()).setTransitionToFullShadeProgress(anyFloat())
+ verify(scrimController, never()).setTransitionToFullShadeProgress(anyFloat(), anyFloat())
verify(notificationPanelController, never()).setTransitionToFullShadeAmount(anyFloat(),
anyBoolean(), anyLong())
verify(qS, never()).setTransitionToFullShadeAmount(anyFloat(), anyFloat())
@@ -242,7 +242,7 @@
transitionController.dragDownAmount = 10f
verify(nsslController).setTransitionToFullShadeAmount(anyFloat(), anyFloat())
verify(mediaHierarchyManager).setTransitionToFullShadeAmount(anyFloat())
- verify(scrimController).setTransitionToFullShadeProgress(anyFloat())
+ verify(scrimController).setTransitionToFullShadeProgress(anyFloat(), anyFloat())
verify(notificationPanelController).setTransitionToFullShadeAmount(anyFloat(),
anyBoolean(), anyLong())
verify(qS).setTransitionToFullShadeAmount(anyFloat(), anyFloat())
@@ -311,6 +311,75 @@
}
@Test
+ fun setDragAmount_setsScrimProgressBasedOnScrimDistance() {
+ val distance = 10
+ context.orCreateTestableResources
+ .addOverride(R.dimen.lockscreen_shade_scrim_transition_distance, distance)
+ configurationController.notifyConfigurationChanged()
+
+ transitionController.dragDownAmount = 5f
+
+ verify(scrimController).transitionToFullShadeProgress(
+ progress = eq(0.5f),
+ lockScreenNotificationsProgress = anyFloat()
+ )
+ }
+
+ @Test
+ fun setDragAmount_setsNotificationsScrimProgressBasedOnNotificationsScrimDistanceAndDelay() {
+ val distance = 100
+ val delay = 10
+ context.orCreateTestableResources.addOverride(
+ R.dimen.lockscreen_shade_notifications_scrim_transition_distance, distance)
+ context.orCreateTestableResources.addOverride(
+ R.dimen.lockscreen_shade_notifications_scrim_transition_delay, delay)
+ configurationController.notifyConfigurationChanged()
+
+ transitionController.dragDownAmount = 20f
+
+ verify(scrimController).transitionToFullShadeProgress(
+ progress = anyFloat(),
+ lockScreenNotificationsProgress = eq(0.1f)
+ )
+ }
+
+ @Test
+ fun setDragAmount_dragAmountLessThanNotifDelayDistance_setsNotificationsScrimProgressToZero() {
+ val distance = 100
+ val delay = 50
+ context.orCreateTestableResources.addOverride(
+ R.dimen.lockscreen_shade_notifications_scrim_transition_distance, distance)
+ context.orCreateTestableResources.addOverride(
+ R.dimen.lockscreen_shade_notifications_scrim_transition_delay, delay)
+ configurationController.notifyConfigurationChanged()
+
+ transitionController.dragDownAmount = 20f
+
+ verify(scrimController).transitionToFullShadeProgress(
+ progress = anyFloat(),
+ lockScreenNotificationsProgress = eq(0f)
+ )
+ }
+
+ @Test
+ fun setDragAmount_dragAmountMoreThanTotalDistance_setsNotificationsScrimProgressToOne() {
+ val distance = 100
+ val delay = 50
+ context.orCreateTestableResources.addOverride(
+ R.dimen.lockscreen_shade_notifications_scrim_transition_distance, distance)
+ context.orCreateTestableResources.addOverride(
+ R.dimen.lockscreen_shade_notifications_scrim_transition_delay, delay)
+ configurationController.notifyConfigurationChanged()
+
+ transitionController.dragDownAmount = 999999f
+
+ verify(scrimController).transitionToFullShadeProgress(
+ progress = anyFloat(),
+ lockScreenNotificationsProgress = eq(1f)
+ )
+ }
+
+ @Test
fun setDragDownAmount_inSplitShade_setsValueOnMediaHierarchyManager() {
enableSplitShade()
@@ -328,9 +397,21 @@
}
private fun setSplitShadeEnabled(enabled: Boolean) {
- context.getOrCreateTestableResources().addOverride(
- R.bool.config_use_split_notification_shade, enabled
- )
+ overrideResource(R.bool.config_use_split_notification_shade, enabled)
configurationController.notifyConfigurationChanged()
}
+
+ /**
+ * Wrapper around [ScrimController.transitionToFullShadeProgress] that has named parameters for
+ * clarify and easier refactoring of parameter names.
+ */
+ private fun ScrimController.transitionToFullShadeProgress(
+ progress: Float,
+ lockScreenNotificationsProgress: Float
+ ) {
+ scrimController.setTransitionToFullShadeProgress(
+ progress,
+ lockScreenNotificationsProgress
+ )
+ }
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/KeyguardCoordinatorTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/KeyguardCoordinatorTest.java
index ca8529d..52bacd2 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/KeyguardCoordinatorTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/KeyguardCoordinatorTest.java
@@ -39,13 +39,18 @@
import com.android.systemui.statusbar.policy.KeyguardStateController;
import org.junit.Before;
+import org.junit.Ignore;
import org.junit.runner.RunWith;
import org.mockito.ArgumentCaptor;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
+/**
+ * TODO(b/224771204) Create test cases
+ */
@SmallTest
@RunWith(AndroidTestingRunner.class)
+@Ignore
public class KeyguardCoordinatorTest extends SysuiTestCase {
private static final int NOTIF_USER_ID = 0;
private static final int CURR_USER_ID = 1;
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationEntryManagerInflationTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationEntryManagerInflationTest.java
index 7fc5ece..251ac7d 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationEntryManagerInflationTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationEntryManagerInflationTest.java
@@ -41,6 +41,7 @@
import androidx.asynclayoutinflater.view.AsyncLayoutInflater;
import androidx.test.filters.SmallTest;
+import com.android.internal.logging.MetricsLogger;
import com.android.internal.statusbar.IStatusBarService;
import com.android.internal.util.NotificationMessagingUtil;
import com.android.systemui.R;
@@ -87,6 +88,7 @@
import com.android.systemui.statusbar.policy.HeadsUpManager;
import com.android.systemui.statusbar.policy.InflatedSmartReplyState;
import com.android.systemui.statusbar.policy.InflatedSmartReplyViewHolder;
+import com.android.systemui.statusbar.policy.SmartReplyConstants;
import com.android.systemui.statusbar.policy.SmartReplyStateInflater;
import com.android.systemui.statusbar.policy.dagger.RemoteInputViewSubcomponent;
import com.android.systemui.util.concurrency.FakeExecutor;
@@ -252,13 +254,17 @@
.thenAnswer((Answer<ExpandableNotificationRowController>) invocation ->
new ExpandableNotificationRowController(
viewCaptor.getValue(),
- mListContainer,
- mock(RemoteInputViewSubcomponent.Factory.class),
mock(ActivatableNotificationViewController.class),
+ mock(RemoteInputViewSubcomponent.Factory.class),
+ mock(MetricsLogger.class),
+ mListContainer,
mNotificationMediaManager,
+ mock(SmartReplyConstants.class),
+ mock(SmartReplyController.class),
mock(PluginManager.class),
new FakeSystemClock(),
- "FOOBAR", "FOOBAR",
+ "FOOBAR",
+ "FOOBAR",
mKeyguardBypassController,
mGroupMembershipManager,
mGroupExpansionManager,
@@ -275,8 +281,7 @@
mock(FeatureFlags.class),
mPeopleNotificationIdentifier,
Optional.of(mock(BubblesManager.class)),
- mock(ExpandableNotificationRowDragController.class)
- ));
+ mock(ExpandableNotificationRowDragController.class)));
when(mNotificationRowComponentBuilder.activatableNotificationView(any()))
.thenReturn(mNotificationRowComponentBuilder);
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 72f8f70..1ecb09b 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
@@ -44,6 +44,7 @@
import android.view.LayoutInflater;
import android.widget.RemoteViews;
+import com.android.internal.logging.MetricsLogger;
import com.android.systemui.TestableDependency;
import com.android.systemui.classifier.FalsingCollectorFake;
import com.android.systemui.classifier.FalsingManagerFake;
@@ -54,6 +55,7 @@
import com.android.systemui.statusbar.NotificationMediaManager;
import com.android.systemui.statusbar.NotificationRemoteInputManager;
import com.android.systemui.statusbar.NotificationShadeWindowController;
+import com.android.systemui.statusbar.SmartReplyController;
import com.android.systemui.statusbar.notification.ConversationNotificationProcessor;
import com.android.systemui.statusbar.notification.collection.NotificationEntry;
import com.android.systemui.statusbar.notification.collection.NotificationEntryBuilder;
@@ -73,6 +75,7 @@
import com.android.systemui.statusbar.policy.HeadsUpManagerLogger;
import com.android.systemui.statusbar.policy.InflatedSmartReplyState;
import com.android.systemui.statusbar.policy.InflatedSmartReplyViewHolder;
+import com.android.systemui.statusbar.policy.SmartReplyConstants;
import com.android.systemui.statusbar.policy.SmartReplyStateInflater;
import com.android.systemui.statusbar.policy.dagger.RemoteInputViewSubcomponent;
import com.android.systemui.tests.R;
@@ -505,7 +508,10 @@
mPeopleNotificationIdentifier,
mOnUserInteractionCallback,
Optional.of(mock(BubblesManager.class)),
- mock(NotificationGutsManager.class));
+ mock(NotificationGutsManager.class),
+ mock(MetricsLogger.class),
+ mock(SmartReplyConstants.class),
+ mock(SmartReplyController.class));
row.setAboveShelfChangedListener(aboveShelf -> { });
mBindStage.getStageParams(entry).requireContentViews(extraInflationFlags);
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 bf16e0a..c9de608 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
@@ -134,6 +134,7 @@
@Mock private InteractionJankMonitor mJankMonitor;
@Mock private StackStateLogger mStackLogger;
@Mock private NotificationStackScrollLogger mLogger;
+ @Mock private NotificationStackSizeCalculator mNotificationStackSizeCalculator;
@Captor
private ArgumentCaptor<StatusBarStateController.StateListener> mStateListenerArgumentCaptor;
@@ -186,7 +187,8 @@
mShadeController,
mJankMonitor,
mStackLogger,
- mLogger
+ mLogger,
+ mNotificationStackSizeCalculator
);
when(mNotificationStackScrollLayout.isAttachedToWindow()).thenReturn(true);
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 eafcc35..7a92b96 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
@@ -103,6 +103,7 @@
@Mock private NotificationStackScrollLayoutController mStackScrollLayoutController;
@Mock private UnlockedScreenOffAnimationController mUnlockedScreenOffAnimationController;
@Mock private NotificationShelf mNotificationShelf;
+ @Mock private NotificationStackSizeCalculator mNotificationStackSizeCalculator;
@Before
@UiThreadTest
@@ -138,7 +139,8 @@
// holds a copy of the CUT's instances of these KeyguardBypassController, so they still
// refer to the CUT's member variables, not the spy's member variables.
mStackScrollerInternal = new NotificationStackScrollLayout(getContext(), null);
- mStackScrollerInternal.initView(getContext(), mNotificationSwipeHelper);
+ mStackScrollerInternal.initView(getContext(), mNotificationSwipeHelper,
+ mNotificationStackSizeCalculator);
mStackScroller = spy(mStackScrollerInternal);
mStackScroller.setShelfController(notificationShelfController);
mStackScroller.setCentralSurfaces(mCentralSurfaces);
@@ -161,17 +163,6 @@
}
@Test
- public void testUpdateStackEndHeight_forEndOfStackHeightAnimation() {
- final float nsslHeight = 10f;
- final float bottomMargin = 1f;
- final float topPadding = 1f;
-
- mStackScroller.updateStackEndHeight(nsslHeight, bottomMargin, topPadding);
- final float stackEndHeight = nsslHeight - bottomMargin - topPadding;
- assertTrue(mAmbientState.getStackEndHeight() == stackEndHeight);
- }
-
- @Test
public void testUpdateStackHeight_withDozeAmount_whenDozeChanging() {
final float dozeAmount = 0.5f;
mAmbientState.setDozeAmount(dozeAmount);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationStackSizeCalculatorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationStackSizeCalculatorTest.kt
new file mode 100644
index 0000000..d1848e3
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationStackSizeCalculatorTest.kt
@@ -0,0 +1,266 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.statusbar.notification.stack
+
+import android.service.notification.StatusBarNotification
+import android.testing.AndroidTestingRunner
+import android.view.View.VISIBLE
+import androidx.test.filters.SmallTest
+import com.android.systemui.R
+import com.android.systemui.SysuiTestCase
+import com.android.systemui.statusbar.NotificationLockscreenUserManager
+import com.android.systemui.statusbar.StatusBarState.KEYGUARD
+import com.android.systemui.statusbar.StatusBarState.SHADE
+import com.android.systemui.statusbar.SysuiStatusBarStateController
+import com.android.systemui.statusbar.notification.collection.NotificationEntry
+import com.android.systemui.statusbar.notification.collection.legacy.NotificationGroupManagerLegacy
+import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow
+import com.android.systemui.statusbar.notification.row.ExpandableView
+import com.android.systemui.util.mockito.any
+import com.android.systemui.util.mockito.nullable
+import com.google.common.truth.Truth.assertThat
+import org.junit.Before
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.mockito.Mock
+import org.mockito.Mockito.mock
+import org.mockito.Mockito.`when` as whenever
+import org.mockito.MockitoAnnotations
+
+@SmallTest
+@RunWith(AndroidTestingRunner::class)
+class NotificationStackSizeCalculatorTest : SysuiTestCase() {
+
+ @Mock private lateinit var groupManager: NotificationGroupManagerLegacy
+
+ @Mock private lateinit var notificationLockscreenUserManager: NotificationLockscreenUserManager
+
+ @Mock private lateinit var sysuiStatusBarStateController: SysuiStatusBarStateController
+
+ @Mock private lateinit var stackLayout: NotificationStackScrollLayout
+
+ private val testableResources = mContext.getOrCreateTestableResources()
+
+ private lateinit var sizeCalculator: NotificationStackSizeCalculator
+
+ @Before
+ fun setUp() {
+ MockitoAnnotations.initMocks(this)
+
+ whenever(stackLayout.calculateGapHeight(nullable(), nullable(), any()))
+ .thenReturn(GAP_HEIGHT)
+ whenever(groupManager.isSummaryOfSuppressedGroup(any())).thenReturn(false)
+ with(testableResources) {
+ addOverride(R.integer.keyguard_max_notification_count, -1)
+ addOverride(R.dimen.notification_divider_height, NOTIFICATION_PADDING.toInt())
+ }
+
+ sizeCalculator =
+ NotificationStackSizeCalculator(
+ groupManager = groupManager,
+ lockscreenUserManager = notificationLockscreenUserManager,
+ statusBarStateController = sysuiStatusBarStateController,
+ testableResources.resources)
+ }
+
+ @Test
+ fun computeMaxKeyguardNotifications_zeroSpace_returnZero() {
+ val rows = listOf(createMockRow(height = ROW_HEIGHT, visibleOnLockscreen = true))
+
+ val maxNotifications =
+ computeMaxKeyguardNotifications(rows, availableSpace = 0f, shelfHeight = 0f)
+
+ assertThat(maxNotifications).isEqualTo(0)
+ }
+
+ @Test
+ fun computeMaxKeyguardNotifications_infiniteSpace_returnsAll() {
+ val numberOfRows = 30
+ val rows = createLockscreenRows(numberOfRows)
+
+ val maxNotifications = computeMaxKeyguardNotifications(rows, Float.MAX_VALUE)
+
+ assertThat(maxNotifications).isEqualTo(numberOfRows)
+ }
+
+ @Test
+ fun computeMaxKeyguardNotifications_spaceForOne_returnsOne() {
+ val rowHeight = ROW_HEIGHT
+ val totalSpaceForEachRow = GAP_HEIGHT + rowHeight
+ val shelfHeight =
+ totalSpaceForEachRow / 2 // In this way shelf absence will not leave room for another.
+ val spaceForOne = totalSpaceForEachRow
+ val rows =
+ listOf(
+ createMockRow(rowHeight, visibleOnLockscreen = true),
+ createMockRow(rowHeight, visibleOnLockscreen = true))
+
+ val maxNotifications =
+ computeMaxKeyguardNotifications(
+ rows, availableSpace = spaceForOne, shelfHeight = shelfHeight)
+
+ assertThat(maxNotifications).isEqualTo(1)
+ }
+
+ @Test
+ fun computeMaxKeyguardNotifications_spaceForOne_shelfUsableForLastNotification_returnsTwo() {
+ val rowHeight = ROW_HEIGHT
+ val totalSpaceForEachRow = GAP_HEIGHT + rowHeight
+ val shelfHeight = totalSpaceForEachRow + NOTIFICATION_PADDING
+ val spaceForOne = totalSpaceForEachRow
+ val rows =
+ listOf(
+ createMockRow(rowHeight, visibleOnLockscreen = true),
+ createMockRow(rowHeight, visibleOnLockscreen = true))
+
+ val maxNotifications =
+ computeMaxKeyguardNotifications(
+ rows, availableSpace = spaceForOne, shelfHeight = shelfHeight)
+
+ assertThat(maxNotifications).isEqualTo(1)
+ }
+
+ @Test
+ fun computeMaxKeyguardNotifications_invisibleOnLockscreen_returnsZero() {
+ val rows = listOf(createMockRow(visibleOnLockscreen = false))
+
+ val maxNotifications = computeMaxKeyguardNotifications(rows, Float.MAX_VALUE)
+
+ assertThat(maxNotifications).isEqualTo(0)
+ }
+
+ @Test
+ fun computeMaxKeyguardNotifications_spaceForTwo_returnsTwo() {
+ val rowHeight = ROW_HEIGHT
+ val totalSpaceForEachRow = GAP_HEIGHT + rowHeight
+ val spaceForTwo = totalSpaceForEachRow * 2 + NOTIFICATION_PADDING
+ val rows =
+ listOf(
+ createMockRow(rowHeight, visibleOnLockscreen = true),
+ createMockRow(rowHeight, visibleOnLockscreen = true),
+ createMockRow(rowHeight, visibleOnLockscreen = true))
+
+ val maxNotifications = computeMaxKeyguardNotifications(rows, spaceForTwo, shelfHeight = 0f)
+
+ assertThat(maxNotifications).isEqualTo(2)
+ }
+
+ @Test
+ fun computeHeight_returnsLessThanAvailableSpaceUsedToCalculateMaxNotifications() {
+ val rowHeight = ROW_HEIGHT
+ val shelfHeight = SHELF_HEIGHT
+ val totalSpaceForEachRow = GAP_HEIGHT + rowHeight + NOTIFICATION_PADDING
+ val availableSpace = totalSpaceForEachRow * 2
+ val rows =
+ listOf(
+ createMockRow(rowHeight, visibleOnLockscreen = true),
+ createMockRow(rowHeight, visibleOnLockscreen = true),
+ createMockRow(rowHeight, visibleOnLockscreen = true))
+
+ val maxNotifications = computeMaxKeyguardNotifications(rows, availableSpace, shelfHeight)
+ assertThat(maxNotifications).isEqualTo(2)
+
+ val height = sizeCalculator.computeHeight(stackLayout, maxNotifications, SHELF_HEIGHT)
+ assertThat(height).isAtMost(availableSpace + SHELF_HEIGHT)
+ }
+
+ @Test
+ fun computeHeight_allInvisibleToLockscreen_NotInLockscreen_returnsHigherThanZero() {
+ setOnLockscreen(false)
+ val rowHeight = 10f
+ setupChildren(listOf(createMockRow(rowHeight, visibleOnLockscreen = false)))
+
+ val height =
+ sizeCalculator.computeHeight(
+ stackLayout, maxNotifications = Int.MAX_VALUE, SHELF_HEIGHT)
+
+ assertThat(height).isGreaterThan(rowHeight)
+ }
+
+ @Test
+ fun computeHeight_allInvisibleToLockscreen_onLockscreen_returnsZero() {
+ setOnLockscreen(true)
+ setupChildren(listOf(createMockRow(visibleOnLockscreen = false)))
+
+ val height =
+ sizeCalculator.computeHeight(
+ stackLayout, maxNotifications = Int.MAX_VALUE, SHELF_HEIGHT)
+
+ assertThat(height).isEqualTo(0)
+ }
+
+ private fun computeMaxKeyguardNotifications(
+ rows: List<ExpandableView>,
+ availableSpace: Float,
+ shelfHeight: Float = SHELF_HEIGHT
+ ): Int {
+ setupChildren(rows)
+ return sizeCalculator.computeMaxKeyguardNotifications(
+ stackLayout, availableSpace, shelfHeight)
+ }
+
+ private fun setupChildren(children: List<ExpandableView>) {
+ whenever(stackLayout.getChildAt(any())).thenAnswer { invocation ->
+ val inx = invocation.getArgument<Int>(0)
+ return@thenAnswer children[inx]
+ }
+ whenever(stackLayout.childCount).thenReturn(children.size)
+ }
+
+ private fun createLockscreenRows(number: Int): List<ExpandableNotificationRow> =
+ (1..number).map { createMockRow(visibleOnLockscreen = true) }.toList()
+
+ private fun createMockRow(
+ height: Float = ROW_HEIGHT,
+ visibleOnLockscreen: Boolean = true,
+ isRemoved: Boolean = false,
+ visibility: Int = VISIBLE,
+ summaryOfSuppressed: Boolean = false
+ ): ExpandableNotificationRow {
+ val row = mock(ExpandableNotificationRow::class.java)
+ val entry = mock(NotificationEntry::class.java)
+ val sbn = mock(StatusBarNotification::class.java)
+ whenever(entry.sbn).thenReturn(sbn)
+ whenever(row.entry).thenReturn(entry)
+ whenever(row.isRemoved).thenReturn(isRemoved)
+ whenever(row.visibility).thenReturn(visibility)
+ whenever(notificationLockscreenUserManager.shouldShowOnKeyguard(entry))
+ .thenReturn(visibleOnLockscreen)
+ whenever(groupManager.isSummaryOfSuppressedGroup(sbn)).thenReturn(summaryOfSuppressed)
+ whenever(row.getMinHeight(any())).thenReturn(height.toInt())
+ whenever(row.intrinsicHeight).thenReturn(height.toInt())
+ return row
+ }
+
+ private fun setOnLockscreen(onLockscreen: Boolean) {
+ whenever(sysuiStatusBarStateController.state)
+ .thenReturn(
+ if (onLockscreen) {
+ KEYGUARD
+ } else {
+ SHADE
+ })
+ }
+
+ /** Default dimensions for tests that don't overwrite them. */
+ companion object {
+ const val GAP_HEIGHT = 12f
+ const val NOTIFICATION_PADDING = 3f
+ const val SHELF_HEIGHT = 14f
+ const val ROW_HEIGHT = SHELF_HEIGHT * 3
+ }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationPanelViewControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationPanelViewControllerTest.java
index 4bac08e..06b2038 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationPanelViewControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationPanelViewControllerTest.java
@@ -104,7 +104,6 @@
import com.android.systemui.statusbar.KeyguardAffordanceView;
import com.android.systemui.statusbar.KeyguardIndicationController;
import com.android.systemui.statusbar.LockscreenShadeTransitionController;
-import com.android.systemui.statusbar.NotificationLockscreenUserManager;
import com.android.systemui.statusbar.NotificationRemoteInputManager;
import com.android.systemui.statusbar.NotificationShadeDepthController;
import com.android.systemui.statusbar.NotificationShadeWindowController;
@@ -119,12 +118,12 @@
import com.android.systemui.statusbar.notification.DynamicPrivacyController;
import com.android.systemui.statusbar.notification.NotificationEntryManager;
import com.android.systemui.statusbar.notification.NotificationWakeUpCoordinator;
-import com.android.systemui.statusbar.notification.collection.legacy.NotificationGroupManagerLegacy;
import com.android.systemui.statusbar.notification.stack.AmbientState;
import com.android.systemui.statusbar.notification.stack.NotificationListContainer;
import com.android.systemui.statusbar.notification.stack.NotificationRoundnessManager;
import com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayout;
import com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayoutController;
+import com.android.systemui.statusbar.notification.stack.NotificationStackSizeCalculator;
import com.android.systemui.statusbar.phone.panelstate.PanelExpansionStateManager;
import com.android.systemui.statusbar.policy.ConfigurationController;
import com.android.systemui.statusbar.policy.KeyguardQsUserSwitchController;
@@ -174,8 +173,6 @@
@Mock
private NotificationShelfController mNotificationShelfController;
@Mock
- private NotificationGroupManagerLegacy mGroupManager;
- @Mock
private KeyguardStatusBarView mKeyguardStatusBar;
@Mock
private KeyguardUserSwitcherView mUserSwitcherView;
@@ -200,10 +197,6 @@
@Mock
private DynamicPrivacyController mDynamicPrivacyController;
@Mock
- private ShadeController mShadeController;
- @Mock
- private NotificationLockscreenUserManager mNotificationLockscreenUserManager;
- @Mock
private NotificationEntryManager mNotificationEntryManager;
@Mock
private StatusBarTouchableRegionManager mStatusBarTouchableRegionManager;
@@ -336,6 +329,8 @@
private SysUiState mSysUiState;
@Mock
private NotificationListContainer mNotificationListContainer;
+ @Mock
+ private NotificationStackSizeCalculator mNotificationStackSizeCalculator;
private NotificationPanelViewController.PanelEventsEmitter mPanelEventsEmitter;
private Optional<SysUIUnfoldComponent> mSysUIUnfoldComponent = Optional.empty();
private SysuiStatusBarStateController mStatusBarStateController;
@@ -466,7 +461,7 @@
mFeatureFlags,
coordinator, expansionHandler, mDynamicPrivacyController, mKeyguardBypassController,
mFalsingManager, new FalsingCollectorFake(),
- mNotificationLockscreenUserManager, mNotificationEntryManager,
+ mNotificationEntryManager,
mKeyguardStateController,
mStatusBarStateController,
mStatusBarWindowStateController,
@@ -484,7 +479,6 @@
mKeyguardUserSwitcherComponentFactory,
mKeyguardStatusBarViewComponentFactory,
mLockscreenShadeTransitionController,
- mGroupManager,
mNotificationAreaController,
mAuthController,
mScrimController,
@@ -516,7 +510,8 @@
mSysUiState,
mKeyguardUnlockAnimationController,
mNotificationListContainer,
- mPanelEventsEmitter);
+ mPanelEventsEmitter,
+ mNotificationStackSizeCalculator);
mNotificationPanelViewController.initDependencies(
mCentralSurfaces,
() -> {},
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationQSContainerControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationQSContainerControllerTest.kt
index 83eabb6..6526fab 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationQSContainerControllerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationQSContainerControllerTest.kt
@@ -6,7 +6,6 @@
import android.view.ViewGroup
import android.view.WindowInsets
import android.view.WindowManagerPolicyConstants
-import androidx.annotation.AnyRes
import androidx.annotation.IdRes
import androidx.constraintlayout.widget.ConstraintLayout
import androidx.constraintlayout.widget.ConstraintSet
@@ -104,10 +103,6 @@
windowInsetsCallback = windowInsetsCallbackCaptor.value
}
- private fun overrideResource(@AnyRes id: Int, value: Any) {
- mContext.orCreateTestableResources.addOverride(id, value)
- }
-
@Test
fun testTaskbarVisibleInSplitShade() {
enableSplitShade()
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 0b25467..786a858 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
@@ -16,7 +16,6 @@
package com.android.systemui.statusbar.phone;
-import static com.android.systemui.statusbar.phone.ScrimController.KEYGUARD_SCRIM_ALPHA;
import static com.android.systemui.statusbar.phone.ScrimController.OPAQUE;
import static com.android.systemui.statusbar.phone.ScrimController.SEMI_TRANSPARENT;
import static com.android.systemui.statusbar.phone.ScrimController.TRANSPARENT;
@@ -1263,19 +1262,36 @@
mScrimController.setClipsQsScrim(true);
float progress = 0.5f;
- mScrimController.setTransitionToFullShadeProgress(progress);
+ float lsNotifProgress = 0.3f;
+ mScrimController.setTransitionToFullShadeProgress(progress, lsNotifProgress);
assertEquals(MathUtils.lerp(keyguardAlpha, shadeLockedAlpha, progress),
mNotificationsScrim.getViewAlpha(), 0.2);
progress = 0.0f;
- mScrimController.setTransitionToFullShadeProgress(progress);
+ mScrimController.setTransitionToFullShadeProgress(progress, lsNotifProgress);
assertEquals(MathUtils.lerp(keyguardAlpha, shadeLockedAlpha, progress),
mNotificationsScrim.getViewAlpha(), 0.2);
progress = 1.0f;
- mScrimController.setTransitionToFullShadeProgress(progress);
+ mScrimController.setTransitionToFullShadeProgress(progress, lsNotifProgress);
assertEquals(MathUtils.lerp(keyguardAlpha, shadeLockedAlpha, progress),
mNotificationsScrim.getViewAlpha(), 0.2);
}
+ @Test
+ public void notificationTransparency_followsNotificationScrimProgress() {
+ mScrimController.transitionTo(ScrimState.SHADE_LOCKED);
+ mScrimController.setRawPanelExpansionFraction(1.0f);
+ finishAnimationsImmediately();
+ mScrimController.transitionTo(ScrimState.KEYGUARD);
+ mScrimController.setRawPanelExpansionFraction(1.0f);
+ finishAnimationsImmediately();
+
+ float progress = 0.5f;
+ float notifProgress = 0.3f;
+ mScrimController.setTransitionToFullShadeProgress(progress, notifProgress);
+
+ assertThat(mNotificationsScrim.getViewAlpha()).isEqualTo(notifProgress);
+ }
+
private void assertAlphaAfterExpansion(ScrimView scrim, float expectedAlpha, float expansion) {
mScrimController.setRawPanelExpansionFraction(expansion);
finishAnimationsImmediately();
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 d48ce8c..fa867e2 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
@@ -447,4 +447,15 @@
controllerCaptor.getValue().onIntentStarted(false);
verify(listener).onFinishLaunchNotifActivity(mNotificationRow.getEntry());
}
+
+ @Test
+ public void testNotifActivityStarterEventSourceFinishEvent_postPanelCollapse_noAnimate() {
+ NotifActivityLaunchEvents.Listener listener =
+ mock(NotifActivityLaunchEvents.Listener.class);
+ mLaunchEventsEmitter.registerListener(listener);
+ when(mCentralSurfaces.shouldAnimateLaunch(anyBoolean())).thenReturn(false);
+ mNotificationActivityStarter
+ .onNotificationClicked(mNotificationRow.getEntry().getSbn(), mNotificationRow);
+ verify(listener).onFinishLaunchNotifActivity(mNotificationRow.getEntry());
+ }
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/RemoteInputViewTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/RemoteInputViewTest.java
index 20a3fda..3a0a7c9 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/RemoteInputViewTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/RemoteInputViewTest.java
@@ -114,15 +114,13 @@
mContext.unregisterReceiver(mReceiver);
}
- private void setTestPendingIntent(RemoteInputView view, RemoteInputViewController controller) {
+ private void setTestPendingIntent(RemoteInputViewController controller) {
PendingIntent pendingIntent = PendingIntent.getBroadcast(mContext, 0,
new Intent(TEST_ACTION), PendingIntent.FLAG_MUTABLE);
RemoteInput input = new RemoteInput.Builder(TEST_RESULT_KEY).build();
RemoteInput[] inputs = {input};
- view.setPendingIntent(pendingIntent);
controller.setPendingIntent(pendingIntent);
- view.setRemoteInput(inputs, input, null /* editedSuggestionInfo */);
controller.setRemoteInput(input);
controller.setRemoteInputs(inputs);
}
@@ -137,7 +135,7 @@
RemoteInputView view = RemoteInputView.inflate(mContext, null, row.getEntry(), mController);
RemoteInputViewController controller = bindController(view, row.getEntry());
- setTestPendingIntent(view, controller);
+ setTestPendingIntent(controller);
view.focus();
@@ -177,7 +175,7 @@
RemoteInputView view = RemoteInputView.inflate(mContext, null, row.getEntry(), mController);
RemoteInputViewController controller = bindController(view, row.getEntry());
- setTestPendingIntent(view, controller);
+ setTestPendingIntent(controller);
view.focus();
@@ -235,7 +233,7 @@
RemoteInputView view = RemoteInputView.inflate(mContext, null, row.getEntry(), mController);
RemoteInputViewController controller = bindController(view, row.getEntry());
- setTestPendingIntent(view, controller);
+ setTestPendingIntent(controller);
// Open view, send a reply
view.focus();
@@ -265,7 +263,7 @@
RemoteInputView view = RemoteInputView.inflate(mContext, null, row.getEntry(), mController);
RemoteInputViewController controller = bindController(view, row.getEntry());
- setTestPendingIntent(view, controller);
+ setTestPendingIntent(controller);
// Open view, attach an image
view.focus();
diff --git a/packages/SystemUI/tests/src/com/android/systemui/util/animation/AnimationUtilTest.kt b/packages/SystemUI/tests/src/com/android/systemui/util/animation/AnimationUtilTest.kt
new file mode 100644
index 0000000..92afb03
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/util/animation/AnimationUtilTest.kt
@@ -0,0 +1,51 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.util.animation
+
+import androidx.test.filters.SmallTest
+import com.android.systemui.SysuiTestCase
+import com.google.common.truth.Truth.assertThat
+import org.junit.Test
+import java.lang.IllegalArgumentException
+
+@SmallTest
+class AnimationUtilTest : SysuiTestCase() {
+ @Test
+ fun getMsForFrames_5frames_returns83() {
+ assertThat(AnimationUtil.getMsForFrames(5)).isEqualTo(83L)
+ }
+
+ @Test
+ fun getMsForFrames_7frames_returns117() {
+ assertThat(AnimationUtil.getMsForFrames(7)).isEqualTo(117L)
+ }
+
+ @Test
+ fun getMsForFrames_30frames_returns500() {
+ assertThat(AnimationUtil.getMsForFrames(30)).isEqualTo(500L)
+ }
+
+ @Test
+ fun getMsForFrames_60frames_returns1000() {
+ assertThat(AnimationUtil.getMsForFrames(60)).isEqualTo(1000L)
+ }
+
+ @Test(expected = IllegalArgumentException::class)
+ fun getMsForFrames_negativeFrames_throwsException() {
+ AnimationUtil.getMsForFrames(-1)
+ }
+}
diff --git a/proto/src/camera.proto b/proto/src/camera.proto
index 4082118..38d74e4 100644
--- a/proto/src/camera.proto
+++ b/proto/src/camera.proto
@@ -66,5 +66,5 @@
// The dynamic range profile of the stream
optional int64 dynamic_range_profile = 14;
// The stream use case
- optional int32 stream_use_case = 15;
+ optional int64 stream_use_case = 15;
}
diff --git a/proto/src/metrics_constants/metrics_constants.proto b/proto/src/metrics_constants/metrics_constants.proto
index 3f712dd..3801c24 100644
--- a/proto/src/metrics_constants/metrics_constants.proto
+++ b/proto/src/metrics_constants/metrics_constants.proto
@@ -2260,10 +2260,12 @@
ACCOUNTS_WORK_PROFILE_SETTINGS = 401;
// Settings -> Dev options -> Convert to file encryption
- CONVERT_FBE = 402;
+ // DEPRECATED: this setting was removed in Android T.
+ CONVERT_FBE = 402 [deprecated=true];
// Settings -> Dev options -> Convert to file encryption -> WIPE AND CONVERT...
- CONVERT_FBE_CONFIRM = 403;
+ // DEPRECATED: this setting was removed in Android T.
+ CONVERT_FBE_CONFIRM = 403 [deprecated=true];
// Settings -> Dev options -> Running services
RUNNING_SERVICES = 404;
diff --git a/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java b/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java
index 249ee16..61e3da8 100644
--- a/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java
+++ b/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java
@@ -322,28 +322,28 @@
@Override
public void setImeSessionEnabled(SparseArray<IInputMethodSession> sessions,
boolean enabled) {
- mService.setImeSessionEnabled(sessions, enabled);
+ mService.scheduleSetImeSessionEnabled(sessions, enabled);
}
@Override
public void unbindInput() {
- mService.unbindInput();
+ mService.scheduleUnbindInput();
}
@Override
public void bindInput(InputBinding binding) {
- mService.bindInput(binding);
+ mService.scheduleBindInput(binding);
}
@Override
public void createImeSession(ArraySet<Integer> ignoreSet) {
- mService.createImeSession(ignoreSet);
+ mService.scheduleCreateImeSession(ignoreSet);
}
@Override
public void startInput(IBinder startInputToken, IInputContext inputContext,
EditorInfo editorInfo, boolean restarting) {
- mService.startInput(startInputToken, inputContext, editorInfo, restarting);
+ mService.scheduleStartInput(startInputToken, inputContext, editorInfo, restarting);
}
}
@@ -4377,12 +4377,16 @@
*
* @param binding Information given to an accessibility service about a client connecting to it.
*/
- public void bindInput(InputBinding binding) {
- AccessibilityUserState userState;
+ public void scheduleBindInput(InputBinding binding) {
+ mMainHandler.sendMessage(obtainMessage(AccessibilityManagerService::bindInput, this,
+ binding));
+ }
+
+ private void bindInput(InputBinding binding) {
synchronized (mLock) {
// Keep records of these in case new Accessibility Services are enabled.
mInputBinding = binding;
- userState = getCurrentUserStateLocked();
+ AccessibilityUserState userState = getCurrentUserStateLocked();
for (int i = userState.mBoundServices.size() - 1; i >= 0; i--) {
final AccessibilityServiceConnection service = userState.mBoundServices.get(i);
if (service.requestImeApis()) {
@@ -4395,11 +4399,13 @@
/**
* Unbind input for accessibility services which request ime capabilities.
*/
- public void unbindInput() {
- AccessibilityUserState userState;
- // TODO(b/218182733): Resolve the Imf lock and mLock possible deadlock
+ public void scheduleUnbindInput() {
+ mMainHandler.sendMessage(obtainMessage(AccessibilityManagerService::unbindInput, this));
+ }
+
+ private void unbindInput() {
synchronized (mLock) {
- userState = getCurrentUserStateLocked();
+ AccessibilityUserState userState = getCurrentUserStateLocked();
for (int i = userState.mBoundServices.size() - 1; i >= 0; i--) {
final AccessibilityServiceConnection service = userState.mBoundServices.get(i);
if (service.requestImeApis()) {
@@ -4412,16 +4418,21 @@
/**
* Start input for accessibility services which request ime capabilities.
*/
- public void startInput(IBinder startInputToken, IInputContext inputContext,
+ public void scheduleStartInput(IBinder startInputToken, IInputContext inputContext,
EditorInfo editorInfo, boolean restarting) {
- AccessibilityUserState userState;
+ mMainHandler.sendMessage(obtainMessage(AccessibilityManagerService::startInput, this,
+ startInputToken, inputContext, editorInfo, restarting));
+ }
+
+ private void startInput(IBinder startInputToken, IInputContext inputContext,
+ EditorInfo editorInfo, boolean restarting) {
synchronized (mLock) {
// Keep records of these in case new Accessibility Services are enabled.
mStartInputToken = startInputToken;
mInputContext = inputContext;
mEditorInfo = editorInfo;
mRestarting = restarting;
- userState = getCurrentUserStateLocked();
+ AccessibilityUserState userState = getCurrentUserStateLocked();
for (int i = userState.mBoundServices.size() - 1; i >= 0; i--) {
final AccessibilityServiceConnection service = userState.mBoundServices.get(i);
if (service.requestImeApis()) {
@@ -4435,11 +4446,15 @@
* Request input sessions from all accessibility services which request ime capabilities and
* whose id is not in the ignoreSet
*/
- public void createImeSession(ArraySet<Integer> ignoreSet) {
- AccessibilityUserState userState;
+ public void scheduleCreateImeSession(ArraySet<Integer> ignoreSet) {
+ mMainHandler.sendMessage(obtainMessage(AccessibilityManagerService::createImeSession,
+ this, ignoreSet));
+ }
+
+ private void createImeSession(ArraySet<Integer> ignoreSet) {
synchronized (mLock) {
mInputSessionRequested = true;
- userState = getCurrentUserStateLocked();
+ AccessibilityUserState userState = getCurrentUserStateLocked();
for (int i = userState.mBoundServices.size() - 1; i >= 0; i--) {
final AccessibilityServiceConnection service = userState.mBoundServices.get(i);
if ((!ignoreSet.contains(service.mId)) && service.requestImeApis()) {
@@ -4455,10 +4470,15 @@
* @param sessions Sessions to enable or disable.
* @param enabled True if enable the sessions or false if disable the sessions.
*/
- public void setImeSessionEnabled(SparseArray<IInputMethodSession> sessions, boolean enabled) {
- AccessibilityUserState userState;
+ public void scheduleSetImeSessionEnabled(SparseArray<IInputMethodSession> sessions,
+ boolean enabled) {
+ mMainHandler.sendMessage(obtainMessage(AccessibilityManagerService::setImeSessionEnabled,
+ this, sessions, enabled));
+ }
+
+ private void setImeSessionEnabled(SparseArray<IInputMethodSession> sessions, boolean enabled) {
synchronized (mLock) {
- userState = getCurrentUserStateLocked();
+ AccessibilityUserState userState = getCurrentUserStateLocked();
for (int i = userState.mBoundServices.size() - 1; i >= 0; i--) {
final AccessibilityServiceConnection service = userState.mBoundServices.get(i);
if (sessions.contains(service.mId) && service.requestImeApis()) {
diff --git a/services/accessibility/java/com/android/server/accessibility/magnification/FullScreenMagnificationController.java b/services/accessibility/java/com/android/server/accessibility/magnification/FullScreenMagnificationController.java
index fa32452..ecc45eb 100644
--- a/services/accessibility/java/com/android/server/accessibility/magnification/FullScreenMagnificationController.java
+++ b/services/accessibility/java/com/android/server/accessibility/magnification/FullScreenMagnificationController.java
@@ -18,6 +18,7 @@
import static android.accessibilityservice.AccessibilityTrace.FLAGS_WINDOW_MANAGER_INTERNAL;
import static android.accessibilityservice.MagnificationConfig.MAGNIFICATION_MODE_FULLSCREEN;
+import static android.util.TypedValue.COMPLEX_UNIT_DIP;
import static android.view.accessibility.MagnificationAnimationCallback.STUB_ANIMATION_CALLBACK;
import static com.android.server.accessibility.AccessibilityManagerService.INVALID_SERVICE_ID;
@@ -31,15 +32,20 @@
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
+import android.content.res.CompatibilityInfo;
import android.graphics.Rect;
import android.graphics.Region;
+import android.hardware.display.DisplayManagerInternal;
import android.os.Handler;
import android.os.Message;
import android.text.TextUtils;
+import android.util.DisplayMetrics;
import android.util.MathUtils;
import android.util.Slog;
import android.util.SparseArray;
+import android.util.TypedValue;
import android.view.Display;
+import android.view.DisplayInfo;
import android.view.MagnificationSpec;
import android.view.View;
import android.view.accessibility.MagnificationAnimationCallback;
@@ -93,6 +99,8 @@
// Whether the following typing focus feature for magnification is enabled.
private boolean mMagnificationFollowTypingEnabled = true;
+ private final DisplayManagerInternal mDisplayManagerInternal;
+
/**
* This class implements {@link WindowManagerInternal.MagnificationCallbacks} and holds
* magnification information per display.
@@ -395,6 +403,18 @@
outRegion.set(mMagnificationRegion);
}
+ private DisplayMetrics getDisplayMetricsForId() {
+ final DisplayMetrics outMetrics = new DisplayMetrics();
+ final DisplayInfo displayInfo = mDisplayManagerInternal.getDisplayInfo(mDisplayId);
+ if (displayInfo != null) {
+ displayInfo.getLogicalMetrics(outMetrics,
+ CompatibilityInfo.DEFAULT_COMPATIBILITY_INFO, null);
+ } else {
+ outMetrics.setToDefaults();
+ }
+ return outMetrics;
+ }
+
void requestRectangleOnScreen(int left, int top, int right, int bottom) {
synchronized (mLock) {
final Rect magnifiedFrame = mTempRect;
@@ -408,6 +428,12 @@
final float scrollX;
final float scrollY;
+ // We offset an additional distance for a user to know the surrounding context.
+ DisplayMetrics metrics = getDisplayMetricsForId();
+ final float offsetViewportX = (float) magnifFrameInScreenCoords.width() / 4;
+ final float offsetViewportY =
+ TypedValue.applyDimension(COMPLEX_UNIT_DIP, 10, metrics);
+
if (right - left > magnifFrameInScreenCoords.width()) {
final int direction = TextUtils
.getLayoutDirectionFromLocale(Locale.getDefault());
@@ -417,9 +443,9 @@
scrollX = right - magnifFrameInScreenCoords.right;
}
} else if (left < magnifFrameInScreenCoords.left) {
- scrollX = left - magnifFrameInScreenCoords.left;
+ scrollX = left - magnifFrameInScreenCoords.left - offsetViewportX;
} else if (right > magnifFrameInScreenCoords.right) {
- scrollX = right - magnifFrameInScreenCoords.right;
+ scrollX = right - magnifFrameInScreenCoords.right + offsetViewportX;
} else {
scrollX = 0;
}
@@ -427,9 +453,9 @@
if (bottom - top > magnifFrameInScreenCoords.height()) {
scrollY = top - magnifFrameInScreenCoords.top;
} else if (top < magnifFrameInScreenCoords.top) {
- scrollY = top - magnifFrameInScreenCoords.top;
+ scrollY = top - magnifFrameInScreenCoords.top - offsetViewportY;
} else if (bottom > magnifFrameInScreenCoords.bottom) {
- scrollY = bottom - magnifFrameInScreenCoords.bottom;
+ scrollY = bottom - magnifFrameInScreenCoords.bottom + offsetViewportY;
} else {
scrollY = 0;
}
@@ -687,6 +713,7 @@
mScreenStateObserver = new ScreenStateObserver(mControllerCtx.getContext(), this);
mMagnificationInfoChangedCallback = magnificationInfoChangedCallback;
mScaleProvider = scaleProvider;
+ mDisplayManagerInternal = LocalServices.getService(DisplayManagerInternal.class);
}
/**
diff --git a/services/accessibility/java/com/android/server/accessibility/magnification/GesturesObserver.java b/services/accessibility/java/com/android/server/accessibility/magnification/GesturesObserver.java
index 3d8f5173..a5c8837 100644
--- a/services/accessibility/java/com/android/server/accessibility/magnification/GesturesObserver.java
+++ b/services/accessibility/java/com/android/server/accessibility/magnification/GesturesObserver.java
@@ -114,7 +114,7 @@
* Clears all states to default.
*/
@MainThread
- public void clear() {
+ private void clear() {
for (GestureMatcher matcher : mGestureMatchers) {
matcher.clear();
}
diff --git a/services/accessibility/java/com/android/server/accessibility/magnification/MagnificationGesturesObserver.java b/services/accessibility/java/com/android/server/accessibility/magnification/MagnificationGesturesObserver.java
index 085c343..23cded7 100644
--- a/services/accessibility/java/com/android/server/accessibility/magnification/MagnificationGesturesObserver.java
+++ b/services/accessibility/java/com/android/server/accessibility/magnification/MagnificationGesturesObserver.java
@@ -133,7 +133,7 @@
mDelayedEventQueue = null;
mCallback.onGestureCompleted(gestureId, mLastDownEventTime, delayEventQueue,
event);
- recycleLastEvent();
+ clear();
}
@Override
@@ -149,19 +149,18 @@
mDelayedEventQueue = null;
mCallback.onGestureCancelled(mLastDownEventTime, delayEventQueue,
mLastEvent);
- recycleLastEvent();
+ clear();
}
/**
* Resets all state to default.
*/
- void clear() {
+ private void clear() {
if (DBG) {
Slog.d(LOG_TAG, "clear:" + mDelayedEventQueue);
}
recycleLastEvent();
mLastDownEventTime = 0;
- mGesturesObserver.clear();
if (mDelayedEventQueue != null) {
for (MotionEventInfo eventInfo2: mDelayedEventQueue) {
eventInfo2.recycle();
diff --git a/services/accessibility/java/com/android/server/accessibility/magnification/WindowMagnificationGestureHandler.java b/services/accessibility/java/com/android/server/accessibility/magnification/WindowMagnificationGestureHandler.java
index 820be28..9ff51ee 100644
--- a/services/accessibility/java/com/android/server/accessibility/magnification/WindowMagnificationGestureHandler.java
+++ b/services/accessibility/java/com/android/server/accessibility/magnification/WindowMagnificationGestureHandler.java
@@ -440,21 +440,11 @@
}
@Override
- public void onExit() {
- clear();
- }
-
- @Override
public void onMotionEvent(MotionEvent event, MotionEvent rawEvent, int policyFlags) {
mGesturesObserver.onMotionEvent(event, rawEvent, policyFlags);
}
@Override
- public void clear() {
- mGesturesObserver.clear();
- }
-
- @Override
public String toString() {
return "DetectingState{"
+ ", mGestureTimeoutObserver =" + mGesturesObserver
diff --git a/services/api/current.txt b/services/api/current.txt
index 5a28802..780fccf 100644
--- a/services/api/current.txt
+++ b/services/api/current.txt
@@ -47,6 +47,9 @@
package com.android.server.pm {
public interface PackageManagerLocal {
+ method public void reconcileSdkData(@Nullable String, @NonNull String, @NonNull java.util.List<java.lang.String>, int, int, int, @NonNull String, int) throws java.io.IOException;
+ field public static final int FLAG_STORAGE_CE = 2; // 0x2
+ field public static final int FLAG_STORAGE_DE = 1; // 0x1
}
}
diff --git a/services/autofill/java/com/android/server/autofill/Session.java b/services/autofill/java/com/android/server/autofill/Session.java
index e0fa67f..0d334e5 100644
--- a/services/autofill/java/com/android/server/autofill/Session.java
+++ b/services/autofill/java/com/android/server/autofill/Session.java
@@ -18,9 +18,9 @@
import static android.service.autofill.AutofillFieldClassificationService.EXTRA_SCORES;
import static android.service.autofill.AutofillService.EXTRA_FILL_RESPONSE;
-import static android.service.autofill.FillRequest.FLAG_ACTIVITY_START;
import static android.service.autofill.FillRequest.FLAG_MANUAL_REQUEST;
import static android.service.autofill.FillRequest.FLAG_PASSWORD_INPUT_TYPE;
+import static android.service.autofill.FillRequest.FLAG_SUPPORTS_FILL_DIALOG;
import static android.service.autofill.FillRequest.FLAG_VIEW_NOT_FOCUSED;
import static android.service.autofill.FillRequest.INVALID_REQUEST_ID;
import static android.view.autofill.AutofillManager.ACTION_RESPONSE_EXPIRED;
@@ -965,7 +965,7 @@
mService.getRemoteInlineSuggestionRenderServiceLocked();
if ((mSessionFlags.mInlineSupportedByService || mSessionFlags.mClientSuggestionsEnabled)
&& remoteRenderService != null
- && (isViewFocusedLocked(flags) || (isRequestFromActivityStarted(flags)))) {
+ && (isViewFocusedLocked(flags) || (isRequestSupportFillDialog(flags)))) {
final Consumer<InlineSuggestionsRequest> inlineSuggestionsRequestConsumer;
if (mSessionFlags.mClientSuggestionsEnabled) {
final int finalRequestId = requestId;
@@ -1011,8 +1011,8 @@
requestAssistStructureLocked(requestId, flags);
}
- private boolean isRequestFromActivityStarted(int flags) {
- return (flags & FLAG_ACTIVITY_START) != 0;
+ private boolean isRequestSupportFillDialog(int flags) {
+ return (flags & FLAG_SUPPORTS_FILL_DIALOG) != 0;
}
@GuardedBy("mLock")
@@ -3002,7 +3002,7 @@
// View is triggering autofill.
mCurrentViewId = viewState.id;
viewState.update(value, virtualBounds, flags);
- if (!isRequestFromActivityStarted(flags)) {
+ if (!isRequestSupportFillDialog(flags)) {
mSessionFlags.mFillDialogDisabled = true;
}
requestNewFillResponseLocked(viewState, ViewState.STATE_STARTED_SESSION, flags);
diff --git a/services/backup/java/com/android/server/backup/UserBackupManagerService.java b/services/backup/java/com/android/server/backup/UserBackupManagerService.java
index e10151d..1af35af 100644
--- a/services/backup/java/com/android/server/backup/UserBackupManagerService.java
+++ b/services/backup/java/com/android/server/backup/UserBackupManagerService.java
@@ -89,8 +89,6 @@
import android.os.SystemClock;
import android.os.UserHandle;
import android.os.WorkSource;
-import android.os.storage.IStorageManager;
-import android.os.storage.StorageManager;
import android.provider.Settings;
import android.text.TextUtils;
import android.util.ArraySet;
@@ -325,7 +323,6 @@
private final ActivityManagerInternal mActivityManagerInternal;
private PowerManager mPowerManager;
private final AlarmManager mAlarmManager;
- private final IStorageManager mStorageManager;
private final BackupManagerConstants mConstants;
private final BackupWakeLock mWakelock;
private final BackupHandler mBackupHandler;
@@ -536,7 +533,6 @@
mBackupPasswordManager = null;
mPackageManagerBinder = null;
mActivityManager = null;
- mStorageManager = null;
mBackupManagerBinder = null;
mScheduledBackupEligibility = null;
}
@@ -560,7 +556,6 @@
mAlarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
mPowerManager = (PowerManager) context.getSystemService(Context.POWER_SERVICE);
- mStorageManager = IStorageManager.Stub.asInterface(ServiceManager.getService("mount"));
Objects.requireNonNull(parent, "parent cannot be null");
mBackupManagerBinder = BackupManagerService.asInterface(parent.asBinder());
@@ -2077,26 +2072,6 @@
}
}
- /** For adb backup/restore. */
- public boolean deviceIsEncrypted() {
- try {
- return mStorageManager.getEncryptionState()
- != StorageManager.ENCRYPTION_STATE_NONE
- && mStorageManager.getPasswordType()
- != StorageManager.CRYPT_TYPE_DEFAULT;
- } catch (Exception e) {
- // If we can't talk to the storagemanager service we have a serious problem; fail
- // "secure" i.e. assuming that the device is encrypted.
- Slog.e(
- TAG,
- addUserIdToLogMessage(
- mUserId,
- "Unable to communicate with storagemanager service: "
- + e.getMessage()));
- return true;
- }
- }
-
// ----- Full-data backup scheduling -----
/**
diff --git a/services/backup/java/com/android/server/backup/fullbackup/PerformAdbBackupTask.java b/services/backup/java/com/android/server/backup/fullbackup/PerformAdbBackupTask.java
index 7ee307e..ec58e17 100644
--- a/services/backup/java/com/android/server/backup/fullbackup/PerformAdbBackupTask.java
+++ b/services/backup/java/com/android/server/backup/fullbackup/PerformAdbBackupTask.java
@@ -320,12 +320,6 @@
try {
boolean encrypting = (mEncryptPassword != null && mEncryptPassword.length() > 0);
- // Only allow encrypted backups of encrypted devices
- if (mUserBackupManagerService.deviceIsEncrypted() && !encrypting) {
- Slog.e(TAG, "Unencrypted backup of encrypted device; aborting");
- return;
- }
-
OutputStream finalOutput = ofstream;
// Verify that the given password matches the currently-active
diff --git a/services/cloudsearch/java/com/android/server/cloudsearch/CloudSearchPerUserService.java b/services/cloudsearch/java/com/android/server/cloudsearch/CloudSearchPerUserService.java
index 116c739..8e0e395 100644
--- a/services/cloudsearch/java/com/android/server/cloudsearch/CloudSearchPerUserService.java
+++ b/services/cloudsearch/java/com/android/server/cloudsearch/CloudSearchPerUserService.java
@@ -107,6 +107,10 @@
@GuardedBy("mLock")
public void onSearchLocked(@NonNull SearchRequest searchRequest,
@NonNull ICloudSearchManagerCallback callback) {
+ if (mRemoteComponentName == null) {
+ return;
+ }
+
String filterList = searchRequest.getSearchConstraints().containsKey(
SearchRequest.CONSTRAINT_SEARCH_PROVIDER_FILTER)
? searchRequest.getSearchConstraints().getString(
diff --git a/services/companion/java/com/android/server/companion/AssociationRequestsProcessor.java b/services/companion/java/com/android/server/companion/AssociationRequestsProcessor.java
index bf8b18c..7a5fa62 100644
--- a/services/companion/java/com/android/server/companion/AssociationRequestsProcessor.java
+++ b/services/companion/java/com/android/server/companion/AssociationRequestsProcessor.java
@@ -51,6 +51,7 @@
import android.os.RemoteException;
import android.os.ResultReceiver;
import android.os.UserHandle;
+import android.util.Log;
import android.util.PackageUtils;
import android.util.Slog;
@@ -332,13 +333,28 @@
}
}
- String[] sameOemPackages = mContext.getResources()
+ // Below we check if the requesting package is allowlisted (usually by the OEM) for creating
+ // CDM associations without user confirmation (prompt).
+ // For this we'll check to config arrays:
+ // - com.android.internal.R.array.config_companionDevicePackages
+ // and
+ // - com.android.internal.R.array.config_companionDeviceCerts.
+ // Both arrays are expected to contain similar number of entries.
+ // config_companionDevicePackages contains package names of the allowlisted packages.
+ // config_companionDeviceCerts contains SHA256 digests of the signatures of the
+ // corresponding packages.
+ // If a package may be signed with one of several certificates, its package name would
+ // appear multiple times in the config_companionDevicePackages, with different entries
+ // (one for each of the valid signing certificates) at the corresponding positions in
+ // config_companionDeviceCerts.
+ final String[] allowlistedPackages = mContext.getResources()
.getStringArray(com.android.internal.R.array.config_companionDevicePackages);
- if (!ArrayUtils.contains(sameOemPackages, packageName)) {
- Slog.w(TAG, packageName
- + " can not silently create associations due to no package found."
- + " Packages from OEM: " + Arrays.toString(sameOemPackages)
- );
+ if (!ArrayUtils.contains(allowlistedPackages, packageName)) {
+ if (DEBUG) {
+ Log.d(TAG, packageName + " is not allowlisted for creating associations "
+ + "without user confirmation (prompt)");
+ Log.v(TAG, "Allowlisted packages=" + Arrays.toString(allowlistedPackages));
+ }
return false;
}
@@ -361,44 +377,41 @@
}
}
- String[] sameOemCerts = mContext.getResources()
+ final String[] allowlistedPackagesSignatureDigests = mContext.getResources()
.getStringArray(com.android.internal.R.array.config_companionDeviceCerts);
-
- Signature[] signatures = mPackageManager.getPackage(packageName).getSigningDetails()
- .getSignatures();
- String[] apkCerts = PackageUtils.computeSignaturesSha256Digests(signatures);
-
- Set<String> sameOemPackageCerts =
- getSameOemPackageCerts(packageName, sameOemPackages, sameOemCerts);
-
- for (String cert : apkCerts) {
- if (sameOemPackageCerts.contains(cert)) {
- return true;
+ final Set<String> allowlistedSignatureDigestsForRequestingPackage = new HashSet<>();
+ for (int i = 0; i < allowlistedPackages.length; i++) {
+ if (allowlistedPackages[i].equals(packageName)) {
+ final String digest = allowlistedPackagesSignatureDigests[i].replaceAll(":", "");
+ allowlistedSignatureDigestsForRequestingPackage.add(digest);
}
}
- Slog.w(TAG, packageName
- + " can not silently create associations. " + packageName
- + " has SHA256 certs from APK: " + Arrays.toString(apkCerts)
- + " and from OEM: " + Arrays.toString(sameOemCerts)
- );
+ final Signature[] requestingPackageSignatures = mPackageManager.getPackage(packageName)
+ .getSigningDetails().getSignatures();
+ final String[] requestingPackageSignatureDigests =
+ PackageUtils.computeSignaturesSha256Digests(requestingPackageSignatures);
- return false;
- }
-
- private static Set<String> getSameOemPackageCerts(
- String packageName, String[] oemPackages, String[] sameOemCerts) {
- Set<String> sameOemPackageCerts = new HashSet<>();
-
- // Assume OEM may enter same package name in the parallel string array with
- // multiple APK certs corresponding to it
- for (int i = 0; i < oemPackages.length; i++) {
- if (oemPackages[i].equals(packageName)) {
- sameOemPackageCerts.add(sameOemCerts[i].replaceAll(":", ""));
+ boolean requestingPackageSignatureAllowlisted = false;
+ for (String signatureDigest : requestingPackageSignatureDigests) {
+ if (allowlistedSignatureDigestsForRequestingPackage.contains(signatureDigest)) {
+ requestingPackageSignatureAllowlisted = true;
+ break;
}
}
- return sameOemPackageCerts;
+ if (!requestingPackageSignatureAllowlisted) {
+ Slog.w(TAG, "Certificate mismatch for allowlisted package " + packageName);
+ if (DEBUG) {
+ Log.d(TAG, " > allowlisted signatures for " + packageName + ": ["
+ + String.join(", ", allowlistedSignatureDigestsForRequestingPackage)
+ + "]");
+ Log.d(TAG, " > actual signatures for " + packageName + ": "
+ + Arrays.toString(requestingPackageSignatureDigests));
+ }
+ }
+
+ return requestingPackageSignatureAllowlisted;
}
/**
diff --git a/services/companion/java/com/android/server/companion/CompanionApplicationController.java b/services/companion/java/com/android/server/companion/CompanionApplicationController.java
index f32eebc..2a83a3c 100644
--- a/services/companion/java/com/android/server/companion/CompanionApplicationController.java
+++ b/services/companion/java/com/android/server/companion/CompanionApplicationController.java
@@ -49,7 +49,7 @@
* The following is the list of the APIs provided by {@link CompanionApplicationController} (to be
* utilized by {@link CompanionDeviceManagerService}):
* <ul>
- * <li> {@link #bindCompanionApplication(int, String)}
+ * <li> {@link #bindCompanionApplication(int, String, boolean)}
* <li> {@link #unbindCompanionApplication(int, String)}
* <li> {@link #notifyCompanionApplicationDeviceAppeared(AssociationInfo)}
* <li> {@link #notifyCompanionApplicationDeviceDisappeared(AssociationInfo)}
@@ -103,8 +103,12 @@
mCompanionServicesRegister.invalidate(userId);
}
- void bindCompanionApplication(@UserIdInt int userId, @NonNull String packageName) {
- if (DEBUG) Log.i(TAG, "bind() u" + userId + "/" + packageName);
+ void bindCompanionApplication(@UserIdInt int userId, @NonNull String packageName,
+ boolean bindImportant) {
+ if (DEBUG) {
+ Log.i(TAG, "bind() u" + userId + "/" + packageName
+ + " important=" + bindImportant);
+ }
final List<ComponentName> companionServices =
mCompanionServicesRegister.forPackage(userId, packageName);
@@ -125,7 +129,8 @@
}
serviceConnectors = CollectionUtils.map(companionServices, componentName ->
- new CompanionDeviceServiceConnector(mContext, userId, componentName));
+ CompanionDeviceServiceConnector.newInstance(mContext, userId,
+ componentName, bindImportant));
mBoundCompanionApplications.setValueForPackage(userId, packageName, serviceConnectors);
}
diff --git a/services/companion/java/com/android/server/companion/CompanionDeviceManagerService.java b/services/companion/java/com/android/server/companion/CompanionDeviceManagerService.java
index eaa99f7..13a5a28 100644
--- a/services/companion/java/com/android/server/companion/CompanionDeviceManagerService.java
+++ b/services/companion/java/com/android/server/companion/CompanionDeviceManagerService.java
@@ -254,9 +254,12 @@
final int userId = association.getUserId();
final String packageName = association.getPackageName();
+ // Set bindImportant to true when the association is self-managed to avoid the target
+ // service being killed.
+ final boolean bindImportant = association.isSelfManaged();
if (!mCompanionAppController.isCompanionApplicationBound(userId, packageName)) {
- mCompanionAppController.bindCompanionApplication(userId, packageName);
+ mCompanionAppController.bindCompanionApplication(userId, packageName, bindImportant);
} else if (DEBUG) {
Log.i(TAG, "u" + userId + "\\" + packageName + " is already bound");
}
diff --git a/services/companion/java/com/android/server/companion/CompanionDeviceServiceConnector.java b/services/companion/java/com/android/server/companion/CompanionDeviceServiceConnector.java
index f2a58b7..a6bd480 100644
--- a/services/companion/java/com/android/server/companion/CompanionDeviceServiceConnector.java
+++ b/services/companion/java/com/android/server/companion/CompanionDeviceServiceConnector.java
@@ -16,6 +16,7 @@
package com.android.server.companion;
+import static android.content.Context.BIND_ALMOST_PERCEPTIBLE;
import static android.content.Context.BIND_IMPORTANT;
import static android.os.Process.THREAD_PRIORITY_DEFAULT;
@@ -44,7 +45,6 @@
class CompanionDeviceServiceConnector extends ServiceConnector.Impl<ICompanionDeviceService> {
private static final String TAG = "CompanionDevice_ServiceConnector";
private static final boolean DEBUG = false;
- private static final int BINDING_FLAGS = BIND_IMPORTANT;
/** Listener for changes to the state of the {@link CompanionDeviceServiceConnector} */
interface Listener {
@@ -53,11 +53,35 @@
private final @UserIdInt int mUserId;
private final @NonNull ComponentName mComponentName;
+ // IMPORTANT: this can (and will!) be null (at the moment, CompanionApplicationController only
+ // installs a listener to the primary ServiceConnector), hence we should always null-check the
+ // reference before calling on it.
private @Nullable Listener mListener;
- CompanionDeviceServiceConnector(@NonNull Context context, @UserIdInt int userId,
- @NonNull ComponentName componentName) {
- super(context, buildIntent(componentName), BINDING_FLAGS, userId, null);
+ /**
+ * Create a CompanionDeviceServiceConnector instance.
+ *
+ * When bindImportant is false, the binding flag will be BIND_ALMOST_PERCEPTIBLE
+ * (oom_score_adj = PERCEPTIBLE_MEDIUM_APP = 225). The target service will be treated
+ * as important as a perceptible app (IMPORTANCE_VISIBLE = 200), and will be unbound when
+ * the app is removed from task manager.
+ * When bindImportant is true, the binding flag will be BIND_IMPORTANT
+ * (oom_score_adj = PERCEPTIBLE_MEDIUM_APP = -700). The target service will
+ * have the highest priority to avoid being killed (IMPORTANCE_FOREGROUND = 100).
+ *
+ * One time permission's importance level to keep session alive is
+ * IMPORTANCE_FOREGROUND_SERVICE = 125. In order to kill the one time permission session, the
+ * service importance level should be higher than 125.
+ */
+ static CompanionDeviceServiceConnector newInstance(@NonNull Context context,
+ @UserIdInt int userId, @NonNull ComponentName componentName, boolean bindImportant) {
+ final int bindingFlags = bindImportant ? BIND_IMPORTANT : BIND_ALMOST_PERCEPTIBLE;
+ return new CompanionDeviceServiceConnector(context, userId, componentName, bindingFlags);
+ }
+
+ private CompanionDeviceServiceConnector(@NonNull Context context, @UserIdInt int userId,
+ @NonNull ComponentName componentName, int bindingFlags) {
+ super(context, buildIntent(componentName), bindingFlags, userId, null);
mUserId = userId;
mComponentName = componentName;
}
@@ -101,7 +125,9 @@
if (DEBUG) Log.d(TAG, "onBindingDied() " + mComponentName.toShortString());
- mListener.onBindingDied(mUserId, mComponentName.getPackageName());
+ if (mListener != null) {
+ mListener.onBindingDied(mUserId, mComponentName.getPackageName());
+ }
}
@Override
diff --git a/services/companion/java/com/android/server/companion/presence/BluetoothCompanionDeviceConnectionListener.java b/services/companion/java/com/android/server/companion/presence/BluetoothCompanionDeviceConnectionListener.java
index 1ba198a..823743d 100644
--- a/services/companion/java/com/android/server/companion/presence/BluetoothCompanionDeviceConnectionListener.java
+++ b/services/companion/java/com/android/server/companion/presence/BluetoothCompanionDeviceConnectionListener.java
@@ -94,7 +94,7 @@
int reason) {
if (DEBUG) {
Log.i(TAG, "onDevice_Disconnected() " + btDeviceToString(device));
- Log.d(TAG, " reason=" + disconnectReasonText(reason));
+ Log.d(TAG, " reason=" + disconnectReasonToString(reason));
}
final MacAddress macAddress = MacAddress.fromString(device.getAddress());
diff --git a/services/core/java/com/android/server/MasterClearReceiver.java b/services/core/java/com/android/server/MasterClearReceiver.java
index be2b7f7..7c3a75f 100644
--- a/services/core/java/com/android/server/MasterClearReceiver.java
+++ b/services/core/java/com/android/server/MasterClearReceiver.java
@@ -131,7 +131,7 @@
final UserManager userManager = context.getSystemService(UserManager.class);
final int result = userManager.removeUserWhenPossible(
UserHandle.of(userId), /* overrideDevicePolicy= */ false);
- if (result == UserManager.REMOVE_RESULT_ERROR) {
+ if (!UserManager.isRemoveResultSuccessful(result)) {
Slogf.e(TAG, "Can't remove user %d", userId);
return false;
}
@@ -169,7 +169,7 @@
private String getWorkProfileDeletedTitle(Context context) {
final DevicePolicyManager dpm = context.getSystemService(DevicePolicyManager.class);
- return dpm.getString(WORK_PROFILE_DELETED_TITLE,
+ return dpm.getResources().getString(WORK_PROFILE_DELETED_TITLE,
() -> context.getString(R.string.work_profile_deleted));
}
diff --git a/services/core/java/com/android/server/NetworkTimeUpdateService.java b/services/core/java/com/android/server/NetworkTimeUpdateService.java
index 186ff62..2015dc9 100644
--- a/services/core/java/com/android/server/NetworkTimeUpdateService.java
+++ b/services/core/java/com/android/server/NetworkTimeUpdateService.java
@@ -196,13 +196,15 @@
* Overrides the NTP server config for tests. Passing {@code null} to a parameter clears the
* test value, i.e. so the normal value will be used next time.
*/
- void setServerConfigForTests(@Nullable String hostname, @Nullable Duration timeout) {
+ void setServerConfigForTests(
+ @Nullable String hostname, @Nullable Integer port, @Nullable Duration timeout) {
mContext.enforceCallingPermission(
android.Manifest.permission.SET_TIME, "set NTP server config for tests");
mLocalLog.log("Setting server config for tests: hostname=" + hostname
+ + ", port=" + port
+ ", timeout=" + timeout);
- mTime.setServerConfigForTests(hostname, timeout);
+ mTime.setServerConfigForTests(hostname, port, timeout);
}
private void onPollNetworkTime(int event) {
diff --git a/services/core/java/com/android/server/NetworkTimeUpdateServiceShellCommand.java b/services/core/java/com/android/server/NetworkTimeUpdateServiceShellCommand.java
index 464af01..d7504ce 100644
--- a/services/core/java/com/android/server/NetworkTimeUpdateServiceShellCommand.java
+++ b/services/core/java/com/android/server/NetworkTimeUpdateServiceShellCommand.java
@@ -46,6 +46,7 @@
*/
private static final String SHELL_COMMAND_SET_SERVER_CONFIG = "set_server_config";
private static final String SET_SERVER_CONFIG_HOSTNAME_ARG = "--hostname";
+ private static final String SET_SERVER_CONFIG_PORT_ARG = "--port";
private static final String SET_SERVER_CONFIG_TIMEOUT_ARG = "--timeout_millis";
@NonNull
@@ -87,6 +88,7 @@
private int runSetServerConfig() {
String hostname = null;
+ Integer port = null;
Duration timeout = null;
String opt;
while ((opt = getNextArg()) != null) {
@@ -95,6 +97,10 @@
hostname = getNextArgRequired();
break;
}
+ case SET_SERVER_CONFIG_PORT_ARG: {
+ port = Integer.parseInt(getNextArgRequired());
+ break;
+ }
case SET_SERVER_CONFIG_TIMEOUT_ARG: {
timeout = Duration.ofMillis(Integer.parseInt(getNextArgRequired()));
break;
@@ -104,7 +110,7 @@
}
}
}
- mNetworkTimeUpdateService.setServerConfigForTests(hostname, timeout);
+ mNetworkTimeUpdateService.setServerConfigForTests(hostname, port, timeout);
return 0;
}
@@ -120,8 +126,9 @@
pw.printf(" Refreshes the latest time. Prints whether it was successful.\n");
pw.printf(" %s\n", SHELL_COMMAND_SET_SERVER_CONFIG);
pw.printf(" Sets the NTP server config for tests. The config is not persisted.\n");
- pw.printf(" Options: [%s <hostname>] [%s <millis>]\n",
- SET_SERVER_CONFIG_HOSTNAME_ARG, SET_SERVER_CONFIG_TIMEOUT_ARG);
+ pw.printf(" Options: [%s <hostname>] [%s <port>] [%s <millis>]\n",
+ SET_SERVER_CONFIG_HOSTNAME_ARG, SET_SERVER_CONFIG_PORT_ARG,
+ SET_SERVER_CONFIG_TIMEOUT_ARG);
pw.printf(" Each key/value is optional and must be specified to override the\n");
pw.printf(" normal value, not specifying a key causes it to reset to the original.\n");
pw.println();
diff --git a/services/core/java/com/android/server/StorageManagerService.java b/services/core/java/com/android/server/StorageManagerService.java
index 7075ed3..a2cfe49 100644
--- a/services/core/java/com/android/server/StorageManagerService.java
+++ b/services/core/java/com/android/server/StorageManagerService.java
@@ -3129,220 +3129,6 @@
}
}
- @Override
- public int getEncryptionState() {
- mContext.enforceCallingOrSelfPermission(Manifest.permission.CRYPT_KEEPER,
- "no permission to access the crypt keeper");
-
- try {
- return mVold.fdeComplete();
- } catch (Exception e) {
- Slog.wtf(TAG, e);
- return StorageManager.ENCRYPTION_STATE_ERROR_UNKNOWN;
- }
- }
-
- @Override
- public int decryptStorage(String password) {
- mContext.enforceCallingOrSelfPermission(Manifest.permission.CRYPT_KEEPER,
- "no permission to access the crypt keeper");
-
- if (TextUtils.isEmpty(password)) {
- throw new IllegalArgumentException("password cannot be empty");
- }
-
- if (DEBUG_EVENTS) {
- Slog.i(TAG, "decrypting storage...");
- }
-
- try {
- mVold.fdeCheckPassword(password);
- mHandler.postDelayed(() -> {
- try {
- mVold.fdeRestart();
- } catch (Exception e) {
- Slog.wtf(TAG, e);
- }
- }, DateUtils.SECOND_IN_MILLIS);
- return 0;
- } catch (ServiceSpecificException e) {
- Slog.e(TAG, "fdeCheckPassword failed", e);
- return e.errorCode;
- } catch (Exception e) {
- Slog.wtf(TAG, e);
- return StorageManager.ENCRYPTION_STATE_ERROR_UNKNOWN;
- }
- }
-
- @Override
- public int encryptStorage(int type, String password) {
- mContext.enforceCallingOrSelfPermission(Manifest.permission.CRYPT_KEEPER,
- "no permission to access the crypt keeper");
-
- if (type == StorageManager.CRYPT_TYPE_DEFAULT) {
- password = "";
- } else if (TextUtils.isEmpty(password)) {
- throw new IllegalArgumentException("password cannot be empty");
- }
-
- if (DEBUG_EVENTS) {
- Slog.i(TAG, "encrypting storage...");
- }
-
- try {
- mVold.fdeEnable(type, password, 0);
- } catch (Exception e) {
- Slog.wtf(TAG, e);
- return -1;
- }
-
- return 0;
- }
-
- /** Set the password for encrypting the main key.
- * @param type One of the CRYPTO_TYPE_XXX consts defined in StorageManager.
- * @param password The password to set.
- */
- @Override
- public int changeEncryptionPassword(int type, String password) {
- mContext.enforceCallingOrSelfPermission(Manifest.permission.CRYPT_KEEPER,
- "no permission to access the crypt keeper");
-
- if (StorageManager.isFileEncryptedNativeOnly()) {
- // Not supported on FBE devices
- return -1;
- }
-
- if (type == StorageManager.CRYPT_TYPE_DEFAULT) {
- password = "";
- } else if (TextUtils.isEmpty(password)) {
- throw new IllegalArgumentException("password cannot be empty");
- }
-
- if (DEBUG_EVENTS) {
- Slog.i(TAG, "changing encryption password...");
- }
-
- try {
- mVold.fdeChangePassword(type, password);
- return 0;
- } catch (Exception e) {
- Slog.wtf(TAG, e);
- return -1;
- }
- }
-
- /**
- * Validate a user-supplied password string with cryptfs
- */
- @Override
- public int verifyEncryptionPassword(String password) throws RemoteException {
- // Only the system process is permitted to validate passwords
- if (Binder.getCallingUid() != android.os.Process.SYSTEM_UID) {
- throw new SecurityException("no permission to access the crypt keeper");
- }
-
- mContext.enforceCallingOrSelfPermission(Manifest.permission.CRYPT_KEEPER,
- "no permission to access the crypt keeper");
-
- if (TextUtils.isEmpty(password)) {
- throw new IllegalArgumentException("password cannot be empty");
- }
-
- if (DEBUG_EVENTS) {
- Slog.i(TAG, "validating encryption password...");
- }
-
- try {
- mVold.fdeVerifyPassword(password);
- return 0;
- } catch (Exception e) {
- Slog.wtf(TAG, e);
- return -1;
- }
- }
-
- /**
- * Get the type of encryption used to encrypt the main key.
- * @return The type, one of the CRYPT_TYPE_XXX consts from StorageManager.
- */
- @Override
- public int getPasswordType() {
- mContext.enforceCallingOrSelfPermission(Manifest.permission.CRYPT_KEEPER,
- "no permission to access the crypt keeper");
-
- try {
- return mVold.fdeGetPasswordType();
- } catch (Exception e) {
- Slog.wtf(TAG, e);
- return -1;
- }
- }
-
- /**
- * Set a field in the crypto header.
- * @param field field to set
- * @param contents contents to set in field
- */
- @Override
- public void setField(String field, String contents) throws RemoteException {
- mContext.enforceCallingOrSelfPermission(Manifest.permission.CRYPT_KEEPER,
- "no permission to access the crypt keeper");
-
- if (!StorageManager.isBlockEncrypted()) {
- // Only supported on FDE devices
- return;
- }
-
- try {
- mVold.fdeSetField(field, contents);
- return;
- } catch (Exception e) {
- Slog.wtf(TAG, e);
- return;
- }
- }
-
- /**
- * Gets a field from the crypto header.
- * @param field field to get
- * @return contents of field
- */
- @Override
- public String getField(String field) throws RemoteException {
- mContext.enforceCallingOrSelfPermission(Manifest.permission.CRYPT_KEEPER,
- "no permission to access the crypt keeper");
-
- if (!StorageManager.isBlockEncrypted()) {
- // Only supported on FDE devices
- return null;
- }
-
- try {
- return mVold.fdeGetField(field);
- } catch (Exception e) {
- Slog.wtf(TAG, e);
- return null;
- }
- }
-
- /**
- * Is userdata convertible to file based encryption?
- * @return non zero for convertible
- */
- @Override
- public boolean isConvertibleToFBE() throws RemoteException {
- mContext.enforceCallingOrSelfPermission(Manifest.permission.CRYPT_KEEPER,
- "no permission to access the crypt keeper");
-
- try {
- return mVold.isConvertibleToFbe();
- } catch (Exception e) {
- Slog.wtf(TAG, e);
- return false;
- }
- }
-
/**
* Check whether the device supports filesystem checkpointing.
*
@@ -3408,33 +3194,6 @@
}
@Override
- public String getPassword() throws RemoteException {
- mContext.enforceCallingOrSelfPermission(Manifest.permission.CRYPT_KEEPER,
- "only keyguard can retrieve password");
-
- try {
- return mVold.fdeGetPassword();
- } catch (Exception e) {
- Slog.wtf(TAG, e);
- return null;
- }
- }
-
- @Override
- public void clearPassword() throws RemoteException {
- mContext.enforceCallingOrSelfPermission(Manifest.permission.CRYPT_KEEPER,
- "only keyguard can clear password");
-
- try {
- mVold.fdeClearPassword();
- return;
- } catch (Exception e) {
- Slog.wtf(TAG, e);
- return;
- }
- }
-
- @Override
public void createUserKey(int userId, int serialNumber, boolean ephemeral) {
enforcePermission(android.Manifest.permission.STORAGE_INTERNAL);
diff --git a/services/core/java/com/android/server/UiModeManagerService.java b/services/core/java/com/android/server/UiModeManagerService.java
index 569d480..2dfe947 100644
--- a/services/core/java/com/android/server/UiModeManagerService.java
+++ b/services/core/java/com/android/server/UiModeManagerService.java
@@ -1302,7 +1302,7 @@
pw.print(" mLastBroadcastState="); pw.println(mLastBroadcastState);
pw.print(" mNightMode="); pw.print(mNightMode); pw.print(" (");
- pw.print(Shell.nightModeToStr(mNightMode)); pw.print(") ");
+ pw.print(Shell.nightModeToStr(mNightMode, mNightModeCustomType)); pw.print(") ");
pw.print(" mOverrideOn/Off="); pw.print(mOverrideNightModeOn);
pw.print("/"); pw.print(mOverrideNightModeOff);
@@ -1917,7 +1917,8 @@
public static final String NIGHT_MODE_STR_YES = "yes";
public static final String NIGHT_MODE_STR_NO = "no";
public static final String NIGHT_MODE_STR_AUTO = "auto";
- public static final String NIGHT_MODE_STR_CUSTOM = "custom";
+ public static final String NIGHT_MODE_STR_CUSTOM_SCHEDULE = "custom_schedule";
+ public static final String NIGHT_MODE_STR_CUSTOM_BEDTIME = "custom_bedtime";
public static final String NIGHT_MODE_STR_UNKNOWN = "unknown";
private final IUiModeManager mInterface;
@@ -1931,7 +1932,7 @@
pw.println("UiModeManager service (uimode) commands:");
pw.println(" help");
pw.println(" Print this help text.");
- pw.println(" night [yes|no|auto|custom]");
+ pw.println(" night [yes|no|auto|custom_schedule|custom_bedtime]");
pw.println(" Set or read night mode.");
pw.println(" car [yes|no]");
pw.println(" Set or read car mode.");
@@ -2001,14 +2002,19 @@
}
final int mode = strToNightMode(modeStr);
+ final int customType = strToNightModeCustomType(modeStr);
if (mode >= 0) {
mInterface.setNightMode(mode);
+ if (mode == UiModeManager.MODE_NIGHT_CUSTOM) {
+ mInterface.setNightModeCustomType(customType);
+ }
printCurrentNightMode();
return 0;
} else {
err.println("Error: mode must be '" + NIGHT_MODE_STR_YES + "', '"
+ NIGHT_MODE_STR_NO + "', or '" + NIGHT_MODE_STR_AUTO
- + "', or '" + NIGHT_MODE_STR_CUSTOM + "'");
+ + "', or '" + NIGHT_MODE_STR_CUSTOM_SCHEDULE + "', or '"
+ + NIGHT_MODE_STR_CUSTOM_BEDTIME + "'");
return -1;
}
}
@@ -2016,11 +2022,12 @@
private void printCurrentNightMode() throws RemoteException {
final PrintWriter pw = getOutPrintWriter();
final int currMode = mInterface.getNightMode();
- final String currModeStr = nightModeToStr(currMode);
+ final int customType = mInterface.getNightModeCustomType();
+ final String currModeStr = nightModeToStr(currMode, customType);
pw.println("Night mode: " + currModeStr);
}
- private static String nightModeToStr(int mode) {
+ private static String nightModeToStr(int mode, int customType) {
switch (mode) {
case UiModeManager.MODE_NIGHT_YES:
return NIGHT_MODE_STR_YES;
@@ -2029,7 +2036,12 @@
case UiModeManager.MODE_NIGHT_AUTO:
return NIGHT_MODE_STR_AUTO;
case MODE_NIGHT_CUSTOM:
- return NIGHT_MODE_STR_CUSTOM;
+ if (customType == UiModeManager.MODE_NIGHT_CUSTOM_TYPE_SCHEDULE) {
+ return NIGHT_MODE_STR_CUSTOM_SCHEDULE;
+ }
+ if (customType == UiModeManager.MODE_NIGHT_CUSTOM_TYPE_BEDTIME) {
+ return NIGHT_MODE_STR_CUSTOM_BEDTIME;
+ }
default:
return NIGHT_MODE_STR_UNKNOWN;
}
@@ -2043,13 +2055,25 @@
return UiModeManager.MODE_NIGHT_NO;
case NIGHT_MODE_STR_AUTO:
return UiModeManager.MODE_NIGHT_AUTO;
- case NIGHT_MODE_STR_CUSTOM:
+ case NIGHT_MODE_STR_CUSTOM_SCHEDULE:
+ case NIGHT_MODE_STR_CUSTOM_BEDTIME:
return UiModeManager.MODE_NIGHT_CUSTOM;
default:
return -1;
}
}
+ private static int strToNightModeCustomType(String customTypeStr) {
+ switch (customTypeStr) {
+ case NIGHT_MODE_STR_CUSTOM_BEDTIME:
+ return UiModeManager.MODE_NIGHT_CUSTOM_TYPE_BEDTIME;
+ case NIGHT_MODE_STR_CUSTOM_SCHEDULE:
+ return UiModeManager.MODE_NIGHT_CUSTOM_TYPE_SCHEDULE;
+ default:
+ return -1;
+ }
+ }
+
private int handleCarMode() throws RemoteException {
final PrintWriter err = getErrPrintWriter();
final String modeStr = getNextArg();
diff --git a/services/core/java/com/android/server/VpnManagerService.java b/services/core/java/com/android/server/VpnManagerService.java
index 7b8cce5..c1d8e7b 100644
--- a/services/core/java/com/android/server/VpnManagerService.java
+++ b/services/core/java/com/android/server/VpnManagerService.java
@@ -37,6 +37,7 @@
import android.net.UnderlyingNetworkInfo;
import android.net.Uri;
import android.net.VpnManager;
+import android.net.VpnProfileState;
import android.net.VpnService;
import android.net.util.NetdService;
import android.os.Binder;
@@ -374,6 +375,24 @@
}
/**
+ * Retrieve the VpnProfileState for the profile provisioned by the given package.
+ *
+ * @return the VpnProfileState with current information, or null if there was no profile
+ * provisioned by the given package.
+ * @hide
+ */
+ @Override
+ @Nullable
+ public VpnProfileState getProvisionedVpnProfileState(@NonNull String packageName) {
+ final int callingUid = Binder.getCallingUid();
+ verifyCallingUidAndPackage(packageName, callingUid);
+ final int user = UserHandle.getUserId(callingUid);
+ synchronized (mVpns) {
+ return mVpns.get(user).getProvisionedVpnProfileState(packageName);
+ }
+ }
+
+ /**
* Start legacy VPN, controlling native daemons as needed. Creates a
* secondary thread to perform connection work, returning quickly.
*
diff --git a/services/core/java/com/android/server/am/ActiveServices.java b/services/core/java/com/android/server/am/ActiveServices.java
index 48e3264..b0ab53907 100644
--- a/services/core/java/com/android/server/am/ActiveServices.java
+++ b/services/core/java/com/android/server/am/ActiveServices.java
@@ -3801,6 +3801,18 @@
@GuardedBy("mAm")
void performScheduleRestartLocked(ServiceRecord r, @NonNull String scheduling,
@NonNull String reason, @UptimeMillisLong long now) {
+
+ // If the service is waiting to become a foreground service, remove the pending
+ // SERVICE_FOREGROUND_TIMEOUT_MSG msg, and set fgWaiting to false, so next time the service
+ // is brought up, scheduleServiceForegroundTransitionTimeoutLocked() can be called again and
+ // a new SERVICE_FOREGROUND_TIMEOUT_MSG is scheduled in SERVICE_START_FOREGROUND_TIMEOUT
+ // again.
+ if (r.fgRequired && r.fgWaiting) {
+ mAm.mHandler.removeMessages(
+ ActivityManagerService.SERVICE_FOREGROUND_TIMEOUT_MSG, r);
+ r.fgWaiting = false;
+ }
+
mAm.mHandler.removeCallbacks(r.restarter);
mAm.mHandler.postAtTime(r.restarter, r.nextRestartTime);
r.nextRestartTime = now + r.restartDelay;
@@ -5678,7 +5690,7 @@
void serviceForegroundTimeout(ServiceRecord r) {
ProcessRecord app;
synchronized (mAm) {
- if (!r.fgRequired || r.destroying) {
+ if (!r.fgRequired || !r.fgWaiting || r.destroying) {
return;
}
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index 0735648..36fdb9d 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -406,6 +406,7 @@
import com.android.server.pm.pkg.SELinuxUtil;
import com.android.server.pm.pkg.parsing.ParsingPackageUtils;
import com.android.server.pm.snapshot.PackageDataSnapshot;
+import com.android.server.sdksandbox.SdkSandboxManagerLocal;
import com.android.server.uri.GrantUri;
import com.android.server.uri.NeededUriGrants;
import com.android.server.uri.UriGrantsManagerInternal;
@@ -2911,12 +2912,35 @@
return mAtmInternal.compatibilityInfoForPackage(ai);
}
+ /**
+ * Enforces that the uid that calls a method is not an
+ * {@link UserHandle#isIsolated(int) isolated} uid.
+ *
+ * @param caller the name of the method being called.
+ * @throws SecurityException if the calling uid is an isolated uid.
+ */
/* package */ void enforceNotIsolatedCaller(String caller) {
if (UserHandle.isIsolated(Binder.getCallingUid())) {
throw new SecurityException("Isolated process not allowed to call " + caller);
}
}
+ /**
+ * Enforces that the uid that calls a method is not an
+ * {@link UserHandle#isIsolated(int) isolated} uid or an
+ * {@link Process#isSdkSandboxUid(int) SDK sandbox} uid.
+ *
+ * @param caller the name of the method being called.
+ * @throws SecurityException if the calling uid is an isolated uid or SDK sandbox uid.
+ */
+ void enforceNotIsolatedOrSdkSandboxCaller(String caller) {
+ enforceNotIsolatedCaller(caller);
+
+ if (Process.isSdkSandboxUid(Binder.getCallingUid())) {
+ throw new SecurityException("SDK sandbox process not allowed to call " + caller);
+ }
+ }
+
@Override
public void setPackageScreenCompatMode(String packageName, int mode) {
mActivityTaskManager.setPackageScreenCompatMode(packageName, mode);
@@ -6561,6 +6585,30 @@
final ProcessRecord addAppLocked(ApplicationInfo info, String customProcess, boolean isolated,
boolean disableHiddenApiChecks, boolean disableTestApiChecks,
String abiOverride, int zygotePolicyFlags) {
+ return addAppLocked(
+ info,
+ customProcess,
+ isolated,
+ /* isSdkSandbox= */ false,
+ /* sdkSandboxUid= */ 0,
+ /* sdkSandboxClientAppPackage= */ null,
+ disableHiddenApiChecks,
+ disableTestApiChecks,
+ abiOverride,
+ zygotePolicyFlags);
+ }
+
+ final ProcessRecord addAppLocked(
+ ApplicationInfo info,
+ String customProcess,
+ boolean isolated,
+ boolean isSdkSandbox,
+ int sdkSandboxUid,
+ @Nullable String sdkSandboxClientAppPackage,
+ boolean disableHiddenApiChecks,
+ boolean disableTestApiChecks,
+ String abiOverride,
+ int zygotePolicyFlags) {
ProcessRecord app;
if (!isolated) {
app = getProcessRecordLocked(customProcess != null ? customProcess : info.processName,
@@ -6570,10 +6618,16 @@
}
if (app == null) {
- app = mProcessList.newProcessRecordLocked(info, customProcess, isolated, 0,
- false, 0, null,
+ app = mProcessList.newProcessRecordLocked(
+ info,
+ customProcess,
+ isolated,
+ /* isolatedUid= */0,
+ isSdkSandbox,
+ sdkSandboxUid,
+ sdkSandboxClientAppPackage,
new HostingRecord("added application",
- customProcess != null ? customProcess : info.processName));
+ customProcess != null ? customProcess : info.processName));
updateLruProcessLocked(app, false, null);
updateOomAdjLocked(app, OomAdjuster.OOM_ADJ_REASON_PROCESS_BEGIN);
}
@@ -6583,13 +6637,16 @@
Event.APP_COMPONENT_USED);
// This package really, really can not be stopped.
- try {
- AppGlobals.getPackageManager().setPackageStoppedState(
- info.packageName, false, UserHandle.getUserId(app.uid));
- } catch (RemoteException e) {
- } catch (IllegalArgumentException e) {
- Slog.w(TAG, "Failed trying to unstop package "
- + info.packageName + ": " + e);
+ // TODO: how set package stopped state should work for sdk sandboxes?
+ if (!isSdkSandbox) {
+ try {
+ AppGlobals.getPackageManager().setPackageStoppedState(
+ info.packageName, false, UserHandle.getUserId(app.uid));
+ } catch (RemoteException e) {
+ } catch (IllegalArgumentException e) {
+ Slog.w(TAG, "Failed trying to unstop package "
+ + info.packageName + ": " + e);
+ }
}
if ((info.flags & PERSISTENT_MASK) == PERSISTENT_MASK) {
@@ -9186,6 +9243,10 @@
mAppRestrictionController.dump(pw, "");
}
+ void dumpAppRestrictionController(ProtoOutputStream proto, int uid) {
+ mAppRestrictionController.dumpAsProto(proto, uid);
+ }
+
/**
* Wrapper function to print out debug data filtered by specified arguments.
*/
@@ -9298,6 +9359,29 @@
mProcessList.writeProcessesToProtoLSP(proto, dumpPackage);
}
}
+ } else if ("app-restrictions".equals(cmd)) {
+ int uid = Process.INVALID_UID;
+ boolean error = false;
+ for (int i = 0; i < args.length; i++) {
+ if ("--uid".equals(args[i])) {
+ if (i + 1 < args.length) {
+ try {
+ uid = Integer.parseInt(args[i + 1]);
+ } catch (NumberFormatException e) {
+ error = true;
+ }
+ } else {
+ error = true;
+ }
+ break;
+ }
+ }
+ if (error) {
+ pw.println("Invalid --uid argument");
+ pw.println("Use -h for help.");
+ } else {
+ dumpAppRestrictionController(proto, uid);
+ }
} else {
// default option, dump everything, output is ActivityManagerServiceProto
synchronized (this) {
@@ -12843,7 +12927,7 @@
public Intent registerReceiverWithFeature(IApplicationThread caller, String callerPackage,
String callerFeatureId, String receiverId, IIntentReceiver receiver,
IntentFilter filter, String permission, int userId, int flags) {
- enforceNotIsolatedCaller("registerReceiver");
+ enforceNotIsolatedOrSdkSandboxCaller("registerReceiver");
ArrayList<Intent> stickyIntents = null;
ProcessRecord callerApp = null;
final boolean visibleToInstantApps
@@ -13455,8 +13539,13 @@
}
if (brOptions.getIdForResponseEvent() > 0) {
- enforceUsageStatsPermission(callerPackage, callingUid, callingPid,
- "recordResponseEventWhileInBackground()");
+ // STOPSHIP (206518114): Temporarily check for PACKAGE_USAGE_STATS permission as
+ // well until the clients switch to using the new permission.
+ if (checkPermission(android.Manifest.permission.ACCESS_BROADCAST_RESPONSE_STATS,
+ callingPid, callingUid) != PERMISSION_GRANTED) {
+ enforceUsageStatsPermission(callerPackage, callingUid, callingPid,
+ "recordResponseEventWhileInBackground()");
+ }
}
}
@@ -14387,6 +14476,32 @@
}
}
+ boolean disableHiddenApiChecks = ai.usesNonSdkApi()
+ || (flags & INSTR_FLAG_DISABLE_HIDDEN_API_CHECKS) != 0;
+ boolean disableTestApiChecks = disableHiddenApiChecks
+ || (flags & INSTR_FLAG_DISABLE_TEST_API_CHECKS) != 0;
+
+ if (disableHiddenApiChecks || disableTestApiChecks) {
+ enforceCallingPermission(android.Manifest.permission.DISABLE_HIDDEN_API_CHECKS,
+ "disable hidden API checks");
+ }
+
+ if ((flags & ActivityManager.INSTR_FLAG_INSTRUMENT_SDK_SANDBOX) != 0) {
+ return startInstrumentationOfSdkSandbox(
+ className,
+ profileFile,
+ arguments,
+ watcher,
+ uiAutomationConnection,
+ userId,
+ abiOverride,
+ ii,
+ ai,
+ noRestart,
+ disableHiddenApiChecks,
+ disableTestApiChecks);
+ }
+
ActiveInstrumentation activeInstr = new ActiveInstrumentation(this);
activeInstr.mClass = className;
String defProcess = ai.processName;;
@@ -14411,15 +14526,6 @@
START_FOREGROUND_SERVICES_FROM_BACKGROUND, callingPid, callingUid)
== PackageManager.PERMISSION_GRANTED;
activeInstr.mNoRestart = noRestart;
- boolean disableHiddenApiChecks = ai.usesNonSdkApi()
- || (flags & INSTR_FLAG_DISABLE_HIDDEN_API_CHECKS) != 0;
- boolean disableTestApiChecks = disableHiddenApiChecks
- || (flags & INSTR_FLAG_DISABLE_TEST_API_CHECKS) != 0;
-
- if (disableHiddenApiChecks || disableTestApiChecks) {
- enforceCallingPermission(android.Manifest.permission.DISABLE_HIDDEN_API_CHECKS,
- "disable hidden API checks");
- }
final long origId = Binder.clearCallingIdentity();
@@ -14465,6 +14571,111 @@
return true;
}
+ @GuardedBy("this")
+ private boolean startInstrumentationOfSdkSandbox(
+ ComponentName className,
+ String profileFile,
+ Bundle arguments,
+ IInstrumentationWatcher watcher,
+ IUiAutomationConnection uiAutomationConnection,
+ int userId,
+ String abiOverride,
+ InstrumentationInfo instrumentationInfo,
+ ApplicationInfo sdkSandboxClientAppInfo,
+ boolean noRestart,
+ boolean disableHiddenApiChecks,
+ boolean disableTestApiChecks) {
+
+ if (noRestart) {
+ reportStartInstrumentationFailureLocked(
+ watcher,
+ className,
+ "Instrumenting sdk sandbox with --no-restart flag is not supported");
+ return false;
+ }
+
+ final ApplicationInfo sdkSandboxInfo;
+ try {
+ final PackageManager pm = mContext.getPackageManager();
+ sdkSandboxInfo = pm.getApplicationInfoAsUser(pm.getSdkSandboxPackageName(), 0, userId);
+ } catch (NameNotFoundException e) {
+ reportStartInstrumentationFailureLocked(
+ watcher, className, "Can't find SdkSandbox package");
+ return false;
+ }
+
+ final SdkSandboxManagerLocal sandboxManagerLocal =
+ LocalManagerRegistry.getManager(SdkSandboxManagerLocal.class);
+ if (sandboxManagerLocal == null) {
+ reportStartInstrumentationFailureLocked(
+ watcher, className, "Can't locate SdkSandboxManagerLocal");
+ return false;
+ }
+
+ final String processName = sandboxManagerLocal.getSdkSandboxProcessNameForInstrumentation(
+ sdkSandboxClientAppInfo);
+
+ ActiveInstrumentation activeInstr = new ActiveInstrumentation(this);
+ activeInstr.mClass = className;
+ activeInstr.mTargetProcesses = new String[]{processName};
+ activeInstr.mTargetInfo = sdkSandboxInfo;
+ activeInstr.mProfileFile = profileFile;
+ activeInstr.mArguments = arguments;
+ activeInstr.mWatcher = watcher;
+ activeInstr.mUiAutomationConnection = uiAutomationConnection;
+ activeInstr.mResultClass = className;
+ activeInstr.mHasBackgroundActivityStartsPermission = false;
+ activeInstr.mHasBackgroundForegroundServiceStartsPermission = false;
+ // Instrumenting sdk sandbox without a restart is not supported
+ activeInstr.mNoRestart = false;
+
+ final int callingUid = Binder.getCallingUid();
+ final long token = Binder.clearCallingIdentity();
+ try {
+ sandboxManagerLocal.notifyInstrumentationStarted(
+ sdkSandboxClientAppInfo.packageName, sdkSandboxClientAppInfo.uid);
+ synchronized (mProcLock) {
+ int sdkSandboxUid = Process.toSdkSandboxUid(sdkSandboxClientAppInfo.uid);
+ // Kill the package sdk sandbox process belong to. At this point sdk sandbox is
+ // already killed.
+ forceStopPackageLocked(
+ instrumentationInfo.targetPackage,
+ /* appId= */ -1,
+ /* callerWillRestart= */ true,
+ /* purgeCache= */ false,
+ /* doIt= */ true,
+ /* evenPersistent= */ true,
+ /* uninstalling= */ false,
+ userId,
+ "start instr");
+
+ ProcessRecord app = addAppLocked(
+ sdkSandboxInfo,
+ processName,
+ /* isolated= */ false,
+ /* isSdkSandbox= */ true,
+ sdkSandboxUid,
+ sdkSandboxClientAppInfo.packageName,
+ disableHiddenApiChecks,
+ disableTestApiChecks,
+ abiOverride,
+ ZYGOTE_POLICY_FLAG_EMPTY);
+
+ app.setActiveInstrumentation(activeInstr);
+ activeInstr.mFinished = false;
+ activeInstr.mSourceUid = callingUid;
+ activeInstr.mRunningProcesses.add(app);
+ if (!mActiveInstrumentation.contains(activeInstr)) {
+ mActiveInstrumentation.add(activeInstr);
+ }
+ }
+ } finally {
+ Binder.restoreCallingIdentity(token);
+ }
+
+ return true;
+ }
+
private void instrumentWithoutRestart(ActiveInstrumentation activeInstr,
ApplicationInfo targetInfo) {
ProcessRecord pr;
@@ -14587,7 +14798,17 @@
app.setActiveInstrumentation(null);
}
- if (!instr.mNoRestart) {
+ if (app.isSdkSandbox) {
+ // For sharedUid apps this will kill all sdk sandbox processes, which is not ideal.
+ // TODO(b/209061624): should we call ProcessList.removeProcessLocked instead?
+ killUid(UserHandle.getAppId(app.uid), UserHandle.getUserId(app.uid), "finished instr");
+ final SdkSandboxManagerLocal sandboxManagerLocal =
+ LocalManagerRegistry.getManager(SdkSandboxManagerLocal.class);
+ if (sandboxManagerLocal != null) {
+ sandboxManagerLocal.notifyInstrumentationFinished(
+ app.sdkSandboxClientAppPackage, Process.getAppUidForSdkSandboxUid(app.uid));
+ }
+ } else if (!instr.mNoRestart) {
forceStopPackageLocked(app.info.packageName, -1, false, false, true, true, false,
app.userId,
"finished inst");
diff --git a/services/core/java/com/android/server/am/AppBatteryExemptionTracker.java b/services/core/java/com/android/server/am/AppBatteryExemptionTracker.java
index d1cf004..6f11b00 100644
--- a/services/core/java/com/android/server/am/AppBatteryExemptionTracker.java
+++ b/services/core/java/com/android/server/am/AppBatteryExemptionTracker.java
@@ -26,10 +26,13 @@
import android.annotation.Nullable;
import android.content.Context;
import android.os.SystemClock;
+import android.util.ArrayMap;
import android.util.Pair;
import android.util.Slog;
+import android.util.SparseArray;
import com.android.internal.R;
+import com.android.internal.annotations.GuardedBy;
import com.android.internal.annotations.VisibleForTesting;
import com.android.server.am.AppBatteryExemptionTracker.AppBatteryExemptionPolicy;
import com.android.server.am.AppBatteryExemptionTracker.UidBatteryStates;
@@ -65,6 +68,11 @@
// As it's a UID-based tracker, anywhere which requires a package name, use this default name.
static final String DEFAULT_NAME = "";
+ // As it's a UID-based tracker, while the state change event it receives could be
+ // in the combination of UID + package name, we'd have to leverage each package's state.
+ @GuardedBy("mLock")
+ private UidProcessMap<Integer> mUidPackageStates = new UidProcessMap<>();
+
AppBatteryExemptionTracker(Context context, AppRestrictionController controller) {
this(context, controller, null, null);
}
@@ -103,12 +111,75 @@
.getUidBatteryUsage(uid);
final int stateTypeIndex = stateTypeToIndex(stateType);
synchronized (mLock) {
- UidBatteryStates pkg = mPkgEvents.get(uid, DEFAULT_NAME);
- if (pkg == null) {
- pkg = createAppStateEvents(uid, DEFAULT_NAME);
- mPkgEvents.put(uid, DEFAULT_NAME, pkg);
+ final SparseArray<ArrayMap<String, Integer>> map = mUidPackageStates.getMap();
+ ArrayMap<String, Integer> pkgsStates = map.get(uid);
+ if (pkgsStates == null) {
+ pkgsStates = new ArrayMap<>();
+ map.put(uid, pkgsStates);
}
- pkg.addEvent(start, now, batteryUsage, stateTypeIndex);
+ int states = 0;
+ int indexOfPkg = pkgsStates.indexOfKey(packageName);
+ if (indexOfPkg >= 0) {
+ states = pkgsStates.valueAt(indexOfPkg);
+ } else {
+ pkgsStates.put(packageName, 0);
+ indexOfPkg = pkgsStates.indexOfKey(packageName);
+ }
+ boolean addEvent = false;
+ if (start) {
+ // Check if there is another package within this UID with this type of event start.
+ boolean alreadyStarted = false;
+ for (int i = pkgsStates.size() - 1; i >= 0; i--) {
+ final int s = pkgsStates.valueAt(i);
+ if ((s & stateType) != 0) {
+ alreadyStarted = true;
+ break;
+ }
+ }
+ pkgsStates.setValueAt(indexOfPkg, states | stateType);
+ if (!alreadyStarted) {
+ // This is the first package within this UID with this type of event start.
+ addEvent = true;
+ }
+ } else {
+ states &= ~stateType;
+ pkgsStates.setValueAt(indexOfPkg, states);
+ boolean allStopped = true;
+ for (int i = pkgsStates.size() - 1; i >= 0; i--) {
+ final int s = pkgsStates.valueAt(i);
+ if ((s & stateType) != 0) {
+ allStopped = false;
+ break;
+ }
+ }
+ if (allStopped) {
+ // None of the packages in this UID has an active event of this type.
+ addEvent = true;
+ }
+ if (states == 0) { // None of the states of this package are active, prune it.
+ pkgsStates.removeAt(indexOfPkg);
+ if (pkgsStates.size() == 0) {
+ map.remove(uid);
+ }
+ }
+ }
+ if (addEvent) {
+ UidBatteryStates pkg = mPkgEvents.get(uid, DEFAULT_NAME);
+ if (pkg == null) {
+ pkg = createAppStateEvents(uid, DEFAULT_NAME);
+ mPkgEvents.put(uid, DEFAULT_NAME, pkg);
+ }
+ pkg.addEvent(start, now, batteryUsage, stateTypeIndex);
+ }
+ }
+ }
+
+ @VisibleForTesting
+ @Override
+ void reset() {
+ super.reset();
+ synchronized (mLock) {
+ mUidPackageStates.clear();
}
}
@@ -116,6 +187,7 @@
if (!enabled) {
synchronized (mLock) {
mPkgEvents.clear();
+ mUidPackageStates.clear();
}
}
}
diff --git a/services/core/java/com/android/server/am/AppBatteryTracker.java b/services/core/java/com/android/server/am/AppBatteryTracker.java
index 7cd45fe..690051f 100644
--- a/services/core/java/com/android/server/am/AppBatteryTracker.java
+++ b/services/core/java/com/android/server/am/AppBatteryTracker.java
@@ -28,6 +28,7 @@
import static android.content.pm.PackageManager.PERMISSION_GRANTED;
import static android.os.BatteryConsumer.POWER_COMPONENT_ANY;
import static android.os.BatteryConsumer.PROCESS_STATE_BACKGROUND;
+import static android.os.BatteryConsumer.PROCESS_STATE_CACHED;
import static android.os.BatteryConsumer.PROCESS_STATE_COUNT;
import static android.os.BatteryConsumer.PROCESS_STATE_FOREGROUND;
import static android.os.BatteryConsumer.PROCESS_STATE_FOREGROUND_SERVICE;
@@ -38,7 +39,6 @@
import static com.android.server.am.ActivityManagerDebugConfig.TAG_AM;
import static com.android.server.am.ActivityManagerDebugConfig.TAG_WITH_CLASS_NAME;
import static com.android.server.am.AppRestrictionController.DEVICE_CONFIG_SUBNAMESPACE_PREFIX;
-import static com.android.server.am.BaseAppStateTracker.ONE_MINUTE;
import android.annotation.NonNull;
import android.annotation.Nullable;
@@ -48,6 +48,7 @@
import android.content.pm.ServiceInfo;
import android.content.res.Resources;
import android.content.res.TypedArray;
+import android.os.AppBatteryStatsProto;
import android.os.BatteryConsumer;
import android.os.BatteryConsumer.Dimensions;
import android.os.BatteryStatsInternal;
@@ -64,6 +65,7 @@
import android.util.SparseArray;
import android.util.SparseBooleanArray;
import android.util.TimeUtils;
+import android.util.proto.ProtoOutputStream;
import com.android.internal.R;
import com.android.internal.annotations.GuardedBy;
@@ -71,7 +73,6 @@
import com.android.internal.util.ArrayUtils;
import com.android.server.am.AppBatteryTracker.AppBatteryPolicy;
import com.android.server.am.AppRestrictionController.UidBatteryUsageProvider;
-import com.android.server.am.BaseAppStateTracker.Injector;
import com.android.server.pm.UserManagerInternal;
import java.io.PrintWriter;
@@ -679,11 +680,69 @@
super.dump(pw, prefix);
}
+ @Override
+ void dumpAsProto(ProtoOutputStream proto, int uid) {
+ synchronized (mLock) {
+ final SparseArray<ImmutableBatteryUsage> uidConsumers = mUidBatteryUsageInWindow;
+ if (uid != android.os.Process.INVALID_UID) {
+ final BatteryUsage usage = uidConsumers.get(uid);
+ if (usage != null) {
+ dumpUidStats(proto, uid, usage);
+ }
+ } else {
+ for (int i = 0, size = uidConsumers.size(); i < size; i++) {
+ final int aUid = uidConsumers.keyAt(i);
+ final BatteryUsage usage = uidConsumers.valueAt(i);
+ dumpUidStats(proto, aUid, usage);
+ }
+ }
+ }
+ }
+
+ private void dumpUidStats(ProtoOutputStream proto, int uid, BatteryUsage usage) {
+ if (usage.mUsage == null) {
+ return;
+ }
+
+ final double foregroundUsage = usage.getUsagePowerMah(PROCESS_STATE_FOREGROUND);
+ final double backgroundUsage = usage.getUsagePowerMah(PROCESS_STATE_BACKGROUND);
+ final double fgsUsage = usage.getUsagePowerMah(PROCESS_STATE_FOREGROUND_SERVICE);
+
+ if (foregroundUsage == 0 && backgroundUsage == 0 && fgsUsage == 0) {
+ return;
+ }
+
+ final long token = proto.start(AppBatteryStatsProto.UID_STATS);
+ proto.write(AppBatteryStatsProto.UidStats.UID, uid);
+ dumpProcessStateStats(proto,
+ AppBatteryStatsProto.UidStats.ProcessStateStats.FOREGROUND,
+ foregroundUsage);
+ dumpProcessStateStats(proto,
+ AppBatteryStatsProto.UidStats.ProcessStateStats.BACKGROUND,
+ backgroundUsage);
+ dumpProcessStateStats(proto,
+ AppBatteryStatsProto.UidStats.ProcessStateStats.FOREGROUND_SERVICE,
+ fgsUsage);
+ proto.end(token);
+ }
+
+ private void dumpProcessStateStats(ProtoOutputStream proto, int processState, double powerMah) {
+ if (powerMah == 0) {
+ return;
+ }
+
+ final long token = proto.start(AppBatteryStatsProto.UidStats.PROCESS_STATE_STATS);
+ proto.write(AppBatteryStatsProto.UidStats.ProcessStateStats.PROCESS_STATE, processState);
+ proto.write(AppBatteryStatsProto.UidStats.ProcessStateStats.POWER_MAH, powerMah);
+ proto.end(token);
+ }
+
static class BatteryUsage {
static final int BATTERY_USAGE_INDEX_UNSPECIFIED = PROCESS_STATE_UNSPECIFIED;
static final int BATTERY_USAGE_INDEX_FOREGROUND = PROCESS_STATE_FOREGROUND;
static final int BATTERY_USAGE_INDEX_BACKGROUND = PROCESS_STATE_BACKGROUND;
static final int BATTERY_USAGE_INDEX_FOREGROUND_SERVICE = PROCESS_STATE_FOREGROUND_SERVICE;
+ static final int BATTERY_USAGE_INDEX_CACHED = PROCESS_STATE_CACHED;
static final int BATTERY_USAGE_COUNT = PROCESS_STATE_COUNT;
static final Dimensions[] BATT_DIMENS = new Dimensions[] {
@@ -695,17 +754,20 @@
PROCESS_STATE_BACKGROUND),
new Dimensions(AppBatteryPolicy.DEFAULT_BG_CURRENT_DRAIN_POWER_COMPONENTS,
PROCESS_STATE_FOREGROUND_SERVICE),
+ new Dimensions(AppBatteryPolicy.DEFAULT_BG_CURRENT_DRAIN_POWER_COMPONENTS,
+ PROCESS_STATE_CACHED),
};
@NonNull double[] mUsage;
@Nullable double[] mPercentage;
BatteryUsage() {
- this(0.0d, 0.0d, 0.0d, 0.0d);
+ this(0.0d, 0.0d, 0.0d, 0.0d, 0.0d);
}
- BatteryUsage(double unspecifiedUsage, double fgUsage, double bgUsage, double fgsUsage) {
- mUsage = new double[] {unspecifiedUsage, fgUsage, bgUsage, fgsUsage};
+ BatteryUsage(double unspecifiedUsage, double fgUsage, double bgUsage, double fgsUsage,
+ double cachedUsage) {
+ mUsage = new double[] {unspecifiedUsage, fgUsage, bgUsage, fgsUsage, cachedUsage};
}
BatteryUsage(@NonNull double[] usage) {
@@ -728,7 +790,8 @@
getConsumedPowerNoThrow(consumer, dims[BATTERY_USAGE_INDEX_UNSPECIFIED]),
getConsumedPowerNoThrow(consumer, dims[BATTERY_USAGE_INDEX_FOREGROUND]),
getConsumedPowerNoThrow(consumer, dims[BATTERY_USAGE_INDEX_BACKGROUND]),
- getConsumedPowerNoThrow(consumer, dims[BATTERY_USAGE_INDEX_FOREGROUND_SERVICE])
+ getConsumedPowerNoThrow(consumer, dims[BATTERY_USAGE_INDEX_FOREGROUND_SERVICE]),
+ getConsumedPowerNoThrow(consumer, dims[BATTERY_USAGE_INDEX_CACHED]),
};
}
@@ -798,6 +861,15 @@
return formatBatteryUsage(mUsage);
}
+ double getUsagePowerMah(@BatteryConsumer.ProcessState int processState) {
+ switch (processState) {
+ case PROCESS_STATE_FOREGROUND: return mUsage[1];
+ case PROCESS_STATE_BACKGROUND: return mUsage[2];
+ case PROCESS_STATE_FOREGROUND_SERVICE: return mUsage[3];
+ }
+ return 0;
+ }
+
boolean isValid() {
for (int i = 0; i < mUsage.length; i++) {
if (mUsage[i] < 0.0d) {
@@ -840,19 +912,21 @@
}
private static String formatBatteryUsage(double[] usage) {
- return String.format("%.3f %.3f %.3f %.3f mAh",
+ return String.format("%.3f %.3f %.3f %.3f %.3f mAh",
usage[BATTERY_USAGE_INDEX_UNSPECIFIED],
usage[BATTERY_USAGE_INDEX_FOREGROUND],
usage[BATTERY_USAGE_INDEX_BACKGROUND],
- usage[BATTERY_USAGE_INDEX_FOREGROUND_SERVICE]);
+ usage[BATTERY_USAGE_INDEX_FOREGROUND_SERVICE],
+ usage[BATTERY_USAGE_INDEX_CACHED]);
}
static String formatBatteryUsagePercentage(double[] percentage) {
- return String.format("%4.2f%% %4.2f%% %4.2f%% %4.2f%%",
+ return String.format("%4.2f%% %4.2f%% %4.2f%% %4.2f%% %4.2f%%",
percentage[BATTERY_USAGE_INDEX_UNSPECIFIED],
percentage[BATTERY_USAGE_INDEX_FOREGROUND],
percentage[BATTERY_USAGE_INDEX_BACKGROUND],
- percentage[BATTERY_USAGE_INDEX_FOREGROUND_SERVICE]);
+ percentage[BATTERY_USAGE_INDEX_FOREGROUND_SERVICE],
+ percentage[BATTERY_USAGE_INDEX_CACHED]);
}
private static double getConsumedPowerNoThrow(final UidBatteryConsumer uidConsumer,
@@ -871,8 +945,8 @@
}
ImmutableBatteryUsage(double unspecifiedUsage, double fgUsage, double bgUsage,
- double fgsUsage) {
- super(unspecifiedUsage, fgUsage, bgUsage, fgsUsage);
+ double fgsUsage, double cachedUsage) {
+ super(unspecifiedUsage, fgUsage, bgUsage, fgsUsage, cachedUsage);
}
ImmutableBatteryUsage(@NonNull double[] usage) {
@@ -932,6 +1006,7 @@
static final int BATTERY_USAGE_TYPE_FOREGROUND = 1 << 1;
static final int BATTERY_USAGE_TYPE_BACKGROUND = 1 << 2;
static final int BATTERY_USAGE_TYPE_FOREGROUND_SERVICE = 1 << 3;
+ static final int BATTERY_USAGE_TYPE_CACHED = 1 << 4;
/**
* Whether or not we should enable the monitoring on background current drains.
@@ -1007,8 +1082,8 @@
/**
* The types of battery drain we're checking on each app; if the sum of the battery drain
* exceeds the threshold, it'll be moved to restricted standby bucket; the type here
- * must be one of, or combination of {@link #BATTERY_USAGE_TYPE_BACKGROUND} and
- * {@link #BATTERY_USAGE_TYPE_FOREGROUND_SERVICE}.
+ * must be one of, or combination of {@link #BATTERY_USAGE_TYPE_BACKGROUND},
+ * {@link #BATTERY_USAGE_TYPE_FOREGROUND_SERVICE} and {@link #BATTERY_USAGE_TYPE_CACHED}.
*/
static final String KEY_BG_CURRENT_DRAIN_TYPES_TO_RESTRICTED_BUCKET =
DEVICE_CONFIG_SUBNAMESPACE_PREFIX + "current_drain_types_to_restricted_bucket";
@@ -1016,8 +1091,8 @@
/**
* The types of battery drain we're checking on each app; if the sum of the battery drain
* exceeds the threshold, it'll be moved to background restricted level; the type here
- * must be one of, or combination of {@link #BATTERY_USAGE_TYPE_BACKGROUND} and
- * {@link #BATTERY_USAGE_TYPE_FOREGROUND_SERVICE}.
+ * must be one of, or combination of {@link #BATTERY_USAGE_TYPE_BACKGROUND},
+ * {@link #BATTERY_USAGE_TYPE_FOREGROUND_SERVICE} and {@link #BATTERY_USAGE_TYPE_CACHED}.
*/
static final String KEY_BG_CURRENT_DRAIN_TYPES_TO_BG_RESTRICTED =
DEVICE_CONFIG_SUBNAMESPACE_PREFIX + "current_drain_types_to_bg_restricted";
@@ -1461,6 +1536,9 @@
case BATTERY_USAGE_TYPE_FOREGROUND_SERVICE:
sb.append("FOREGROUND_SERVICE");
break;
+ case BATTERY_USAGE_TYPE_CACHED:
+ sb.append("CACHED");
+ break;
default:
return "[UNKNOWN(" + Integer.toHexString(types) + ")]";
}
diff --git a/services/core/java/com/android/server/am/AppFGSTracker.java b/services/core/java/com/android/server/am/AppFGSTracker.java
index 075402f..246725e 100644
--- a/services/core/java/com/android/server/am/AppFGSTracker.java
+++ b/services/core/java/com/android/server/am/AppFGSTracker.java
@@ -32,18 +32,22 @@
import android.annotation.NonNull;
import android.app.ActivityManagerInternal.ForegroundServiceStateListener;
import android.app.IProcessObserver;
+import android.content.ComponentName;
import android.content.Context;
import android.content.pm.ServiceInfo.ForegroundServiceType;
import android.os.Handler;
import android.os.Message;
import android.os.PowerExemptionManager.ReasonCode;
+import android.os.RemoteException;
import android.os.SystemClock;
import android.os.UserHandle;
import android.provider.DeviceConfig;
+import android.service.notification.NotificationListenerService;
+import android.service.notification.StatusBarNotification;
import android.util.ArrayMap;
-import android.util.ArraySet;
import android.util.Slog;
import android.util.SparseArray;
+import android.util.SparseBooleanArray;
import android.util.TimeUtils;
import com.android.internal.annotations.GuardedBy;
@@ -53,7 +57,6 @@
import com.android.server.am.BaseAppStateEventsTracker.BaseAppStateEventsPolicy;
import com.android.server.am.BaseAppStateTimeEvents.BaseTimeEvent;
import com.android.server.am.BaseAppStateTracker.Injector;
-import com.android.server.notification.NotificationManagerInternal;
import java.io.PrintWriter;
import java.lang.reflect.Constructor;
@@ -72,11 +75,14 @@
private final MyHandler mHandler;
@GuardedBy("mLock")
- private final UidProcessMap<ArraySet<Integer>> mFGSNotificationIDs = new UidProcessMap<>();
+ private final UidProcessMap<SparseBooleanArray> mFGSNotificationIDs = new UidProcessMap<>();
// Unlocked since it's only accessed in single thread.
private final ArrayMap<PackageDurations, Long> mTmpPkgDurations = new ArrayMap<>();
+ @VisibleForTesting
+ final NotificationListener mNotificationListener = new NotificationListener();
+
final IProcessObserver.Stub mProcessObserver = new IProcessObserver.Stub() {
@Override
public void onForegroundActivitiesChanged(int pid, int uid, boolean fg) {
@@ -116,6 +122,8 @@
static final int MSG_FOREGROUND_SERVICES_CHANGED = 2;
static final int MSG_FOREGROUND_SERVICES_NOTIFICATION_UPDATED = 3;
static final int MSG_CHECK_LONG_RUNNING_FGS = 4;
+ static final int MSG_NOTIFICATION_POSTED = 5;
+ static final int MSG_NOTIFICATION_REMOVED = 6;
private final AppFGSTracker mTracker;
@@ -146,6 +154,12 @@
case MSG_CHECK_LONG_RUNNING_FGS:
mTracker.checkLongRunningFgs();
break;
+ case MSG_NOTIFICATION_POSTED:
+ mTracker.handleNotificationPosted((String) msg.obj, msg.arg1, msg.arg2);
+ break;
+ case MSG_NOTIFICATION_REMOVED:
+ mTracker.handleNotificationRemoved((String) msg.obj, msg.arg1, msg.arg2);
+ break;
}
}
}
@@ -223,19 +237,36 @@
private void handleForegroundServiceNotificationUpdated(String packageName, int uid,
int notificationId) {
synchronized (mLock) {
+ SparseBooleanArray notificationIDs = mFGSNotificationIDs.get(uid, packageName);
if (notificationId > 0) {
- ArraySet<Integer> notificationIDs = mFGSNotificationIDs.get(uid, packageName);
if (notificationIDs == null) {
- notificationIDs = new ArraySet<>();
+ notificationIDs = new SparseBooleanArray();
mFGSNotificationIDs.put(uid, packageName, notificationIDs);
}
- notificationIDs.add(notificationId);
+ notificationIDs.put(notificationId, false);
} else if (notificationId < 0) {
- final ArraySet<Integer> notificationIDs = mFGSNotificationIDs.get(uid, packageName);
if (notificationIDs != null) {
- notificationIDs.remove(-notificationId);
- if (notificationIDs.isEmpty()) {
- mFGSNotificationIDs.remove(uid, packageName);
+ final int indexOfKey = notificationIDs.indexOfKey(-notificationId);
+ if (indexOfKey >= 0) {
+ final boolean wasVisible = notificationIDs.valueAt(indexOfKey);
+ notificationIDs.removeAt(indexOfKey);
+ if (notificationIDs.size() == 0) {
+ mFGSNotificationIDs.remove(uid, packageName);
+ }
+ // Walk through the list of FGS notification IDs and see if there are any
+ // visible ones.
+ for (int i = notificationIDs.size() - 1; i >= 0; i--) {
+ if (notificationIDs.valueAt(i)) {
+ // Still visible, nothing to do.
+ return;
+ }
+ }
+ if (wasVisible) {
+ // That was the last visible notification, notify the listeners.
+ notifyListenersOnStateChange(uid, packageName, false,
+ SystemClock.elapsedRealtime(),
+ STATE_TYPE_FGS_WITH_NOTIFICATION);
+ }
}
}
}
@@ -244,20 +275,74 @@
@GuardedBy("mLock")
private boolean hasForegroundServiceNotificationsLocked(String packageName, int uid) {
- final ArraySet<Integer> notificationIDs = mFGSNotificationIDs.get(uid, packageName);
- if (notificationIDs == null || notificationIDs.isEmpty()) {
+ final SparseBooleanArray notificationIDs = mFGSNotificationIDs.get(uid, packageName);
+ if (notificationIDs == null || notificationIDs.size() == 0) {
return false;
}
- final NotificationManagerInternal nm = mInjector.getNotificationManagerInternal();
- final int userId = UserHandle.getUserId(uid);
for (int i = notificationIDs.size() - 1; i >= 0; i--) {
- if (nm.isNotificationShown(packageName, null, notificationIDs.valueAt(i), userId)) {
+ if (notificationIDs.valueAt(i)) {
return true;
}
}
return false;
}
+ private void handleNotificationPosted(String pkgName, int uid, int notificationId) {
+ synchronized (mLock) {
+ final SparseBooleanArray notificationIDs = mFGSNotificationIDs.get(uid, pkgName);
+ final int indexOfKey;
+ if (notificationIDs == null
+ || (indexOfKey = notificationIDs.indexOfKey(notificationId)) < 0) {
+ return;
+ }
+ if (notificationIDs.valueAt(indexOfKey)) {
+ // It's already visible.
+ return;
+ }
+ boolean anyVisible = false;
+ // Walk through the list of FGS notification IDs and see if there are any visible ones.
+ for (int i = notificationIDs.size() - 1; i >= 0; i--) {
+ if (notificationIDs.valueAt(i)) {
+ anyVisible = true;
+ break;
+ }
+ }
+ notificationIDs.setValueAt(indexOfKey, true);
+ if (!anyVisible) {
+ // We didn't have any visible FGS notifications but now we have one,
+ // let the listeners know.
+ notifyListenersOnStateChange(uid, pkgName, true, SystemClock.elapsedRealtime(),
+ STATE_TYPE_FGS_WITH_NOTIFICATION);
+ }
+ }
+ }
+
+ private void handleNotificationRemoved(String pkgName, int uid, int notificationId) {
+ synchronized (mLock) {
+ final SparseBooleanArray notificationIDs = mFGSNotificationIDs.get(uid, pkgName);
+ final int indexOfKey;
+ if (notificationIDs == null
+ || (indexOfKey = notificationIDs.indexOfKey(notificationId)) < 0) {
+ return;
+ }
+ if (!notificationIDs.valueAt(indexOfKey)) {
+ // It's already invisible.
+ return;
+ }
+ notificationIDs.setValueAt(indexOfKey, false);
+ // Walk through the list of FGS notification IDs and see if there are any visible ones.
+ for (int i = notificationIDs.size() - 1; i >= 0; i--) {
+ if (notificationIDs.valueAt(i)) {
+ // Still visible, nothing to do.
+ return;
+ }
+ }
+ // Nothing is visible now, let the listeners know.
+ notifyListenersOnStateChange(uid, pkgName, false, SystemClock.elapsedRealtime(),
+ STATE_TYPE_FGS_WITH_NOTIFICATION);
+ }
+ }
+
@GuardedBy("mLock")
private void scheduleDurationCheckLocked(long now) {
// Look for the active FGS with longest running time till now.
@@ -374,7 +459,19 @@
synchronized (mLock) {
scheduleDurationCheckLocked(SystemClock.elapsedRealtime());
}
+ try {
+ mNotificationListener.registerAsSystemService(mContext,
+ new ComponentName(mContext, NotificationListener.class),
+ UserHandle.USER_ALL);
+ } catch (RemoteException e) {
+ // Intra-process call, should never happen.
+ }
} else {
+ try {
+ mNotificationListener.unregisterAsSystemService();
+ } catch (RemoteException e) {
+ // Intra-process call, should never happen.
+ }
mHandler.removeMessages(MyHandler.MSG_CHECK_LONG_RUNNING_FGS);
synchronized (mLock) {
mPkgEvents.clear();
@@ -436,9 +533,9 @@
boolean hasForegroundServiceNotifications(int uid) {
synchronized (mLock) {
- final SparseArray<ArrayMap<String, ArraySet<Integer>>> map =
+ final SparseArray<ArrayMap<String, SparseBooleanArray>> map =
mFGSNotificationIDs.getMap();
- final ArrayMap<String, ArraySet<Integer>> pkgs = map.get(uid);
+ final ArrayMap<String, SparseBooleanArray> pkgs = map.get(uid);
if (pkgs != null) {
for (int i = pkgs.size() - 1; i >= 0; i--) {
if (hasForegroundServiceNotificationsLocked(pkgs.keyAt(i), uid)) {
@@ -463,7 +560,7 @@
pw.println("APPS WITH ACTIVE FOREGROUND SERVICES:");
prefix = " " + prefix;
synchronized (mLock) {
- final SparseArray<ArrayMap<String, ArraySet<Integer>>> map =
+ final SparseArray<ArrayMap<String, SparseBooleanArray>> map =
mFGSNotificationIDs.getMap();
if (map.size() == 0) {
pw.print(prefix);
@@ -472,7 +569,7 @@
for (int i = 0, size = map.size(); i < size; i++) {
final int uid = map.keyAt(i);
final String uidString = UserHandle.formatUid(uid);
- final ArrayMap<String, ArraySet<Integer>> pkgs = map.valueAt(i);
+ final ArrayMap<String, SparseBooleanArray> pkgs = map.valueAt(i);
for (int j = 0, numOfPkgs = pkgs.size(); j < numOfPkgs; j++) {
final String pkgName = pkgs.keyAt(j);
pw.print(prefix);
@@ -622,6 +719,28 @@
}
}
+ @VisibleForTesting
+ class NotificationListener extends NotificationListenerService {
+ @Override
+ public void onNotificationPosted(StatusBarNotification sbn, RankingMap map) {
+ if (DEBUG_BACKGROUND_FGS_TRACKER) {
+ Slog.i(TAG, "Notification posted: " + sbn);
+ }
+ mHandler.obtainMessage(MyHandler.MSG_NOTIFICATION_POSTED,
+ sbn.getUid(), sbn.getId(), sbn.getPackageName()).sendToTarget();
+ }
+
+ @Override
+ public void onNotificationRemoved(StatusBarNotification sbn, RankingMap rankingMap,
+ int reason) {
+ if (DEBUG_BACKGROUND_FGS_TRACKER) {
+ Slog.i(TAG, "Notification removed: " + sbn);
+ }
+ mHandler.obtainMessage(MyHandler.MSG_NOTIFICATION_REMOVED,
+ sbn.getUid(), sbn.getId(), sbn.getPackageName()).sendToTarget();
+ }
+ }
+
static final class AppFGSPolicy extends BaseAppStateEventsPolicy<AppFGSTracker> {
/**
* Whether or not we should enable the monitoring on abusive FGS.
diff --git a/services/core/java/com/android/server/am/AppPermissionTracker.java b/services/core/java/com/android/server/am/AppPermissionTracker.java
index 69f70ca..622d746 100644
--- a/services/core/java/com/android/server/am/AppPermissionTracker.java
+++ b/services/core/java/com/android/server/am/AppPermissionTracker.java
@@ -17,6 +17,14 @@
package com.android.server.am;
import static android.Manifest.permission.ACCESS_FINE_LOCATION;
+import static android.Manifest.permission.CAMERA;
+import static android.Manifest.permission.RECORD_AUDIO;
+import static android.app.AppOpsManager.OPSTR_CAMERA;
+import static android.app.AppOpsManager.OPSTR_FINE_LOCATION;
+import static android.app.AppOpsManager.OPSTR_RECORD_AUDIO;
+import static android.app.AppOpsManager.OP_NONE;
+import static android.app.AppOpsManager.opToPublicName;
+import static android.app.AppOpsManager.strOpToOp;
import static android.content.pm.PackageManager.PERMISSION_GRANTED;
import static android.os.Process.SYSTEM_UID;
@@ -27,28 +35,37 @@
import static com.android.server.am.BaseAppStateTracker.STATE_TYPE_PERMISSION;
import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.app.AppOpsManager;
import android.content.Context;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager.OnPermissionsChangedListener;
import android.content.pm.PackageManagerInternal;
import android.os.Handler;
import android.os.Message;
+import android.os.RemoteException;
import android.os.SystemClock;
import android.os.UserHandle;
import android.permission.PermissionManager;
import android.provider.DeviceConfig;
+import android.text.TextUtils;
import android.util.ArraySet;
+import android.util.Pair;
import android.util.Slog;
import android.util.SparseArray;
import com.android.internal.annotations.GuardedBy;
+import com.android.internal.app.IAppOpsCallback;
+import com.android.internal.app.IAppOpsService;
import com.android.server.am.AppPermissionTracker.AppPermissionPolicy;
import com.android.server.pm.permission.PermissionManagerServiceInternal;
import java.io.PrintWriter;
import java.lang.reflect.Constructor;
+import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
+import java.util.Objects;
/**
* The tracker for monitoring selected permission state of apps.
@@ -61,8 +78,17 @@
private final MyHandler mHandler;
+ /**
+ * Keep a new instance of callback for each appop we're monitoring,
+ * as the AppOpsService doesn't support monitoring multiple appops with single callback
+ * instance (except the ALL_OPS case).
+ */
+ @GuardedBy("mAppOpsCallbacks")
+ private final SparseArray<MyAppOpsCallback> mAppOpsCallbacks = new SparseArray<>();
+
@GuardedBy("mLock")
- private SparseArray<ArraySet<String>> mUidGrantedPermissionsInMonitor = new SparseArray<>();
+ private SparseArray<ArraySet<UidGrantedPermissionState>> mUidGrantedPermissionsInMonitor =
+ new SparseArray<>();
private volatile boolean mLockedBootCompleted = false;
@@ -82,12 +108,25 @@
mHandler.obtainMessage(MyHandler.MSG_PERMISSIONS_CHANGED, uid, 0).sendToTarget();
}
+ private void handleAppOpsInit() {
+ final ArrayList<Integer> ops = new ArrayList<>();
+ final Pair[] permissions = mInjector.getPolicy().getBgPermissionsInMonitor();
+ for (int i = 0; i < permissions.length; i++) {
+ final Pair<String, Integer> pair = permissions[i];
+ if (pair.second != OP_NONE) {
+ ops.add(pair.second);
+ }
+ }
+ startWatchingMode(ops.toArray(new Integer[ops.size()]));
+ }
+
private void handlePermissionsInit() {
final int[] allUsers = mInjector.getUserManagerInternal().getUserIds();
final PackageManagerInternal pmi = mInjector.getPackageManagerInternal();
final PermissionManagerServiceInternal pm = mInjector.getPermissionManagerServiceInternal();
- final String[] permissions = mInjector.getPolicy().getBgPermissionsInMonitor();
- final SparseArray<ArraySet<String>> uidPerms = mUidGrantedPermissionsInMonitor;
+ final Pair[] permissions = mInjector.getPolicy().getBgPermissionsInMonitor();
+ final SparseArray<ArraySet<UidGrantedPermissionState>> uidPerms =
+ mUidGrantedPermissionsInMonitor;
for (int userId : allUsers) {
final List<ApplicationInfo> apps = pmi.getInstalledApplications(0, userId, SYSTEM_UID);
if (apps == null) {
@@ -96,33 +135,44 @@
final long now = SystemClock.elapsedRealtime();
for (int i = 0, size = apps.size(); i < size; i++) {
final ApplicationInfo ai = apps.get(i);
- for (String permission : permissions) {
- if (pm.checkUidPermission(ai.uid, permission) != PERMISSION_GRANTED) {
+ for (Pair<String, Integer> permission : permissions) {
+ final UidGrantedPermissionState state = new UidGrantedPermissionState(
+ ai.uid, permission.first, permission.second);
+ if (!state.isGranted()) {
+ // No need to track it.
continue;
}
synchronized (mLock) {
- ArraySet<String> grantedPermissions = uidPerms.get(ai.uid);
+ ArraySet<UidGrantedPermissionState> grantedPermissions =
+ uidPerms.get(ai.uid);
if (grantedPermissions == null) {
- grantedPermissions = new ArraySet<String>();
+ grantedPermissions = new ArraySet<UidGrantedPermissionState>();
uidPerms.put(ai.uid, grantedPermissions);
+ // This UID has at least one active permission-in-interest now,
+ // let the listeners know.
+ notifyListenersOnStateChange(ai.uid, DEFAULT_NAME, true, now,
+ STATE_TYPE_PERMISSION);
}
- grantedPermissions.add(permission);
- notifyListenersOnStateChange(ai.uid, DEFAULT_NAME, true, now,
- STATE_TYPE_PERMISSION);
+ grantedPermissions.add(state);
}
}
}
}
}
+ private void handleAppOpsDestroy() {
+ stopWatchingMode();
+ }
+
private void handlePermissionsDestroy() {
synchronized (mLock) {
- final SparseArray<ArraySet<String>> uidPerms = mUidGrantedPermissionsInMonitor;
+ final SparseArray<ArraySet<UidGrantedPermissionState>> uidPerms =
+ mUidGrantedPermissionsInMonitor;
final long now = SystemClock.elapsedRealtime();
for (int i = 0, size = uidPerms.size(); i < size; i++) {
final int uid = uidPerms.keyAt(i);
- final ArraySet<String> grantedPermissions = uidPerms.valueAt(i);
- for (int j = 0, numOfPerms = grantedPermissions.size(); j < numOfPerms; j++) {
+ final ArraySet<UidGrantedPermissionState> grantedPermissions = uidPerms.valueAt(i);
+ if (grantedPermissions.size() > 0) {
notifyListenersOnStateChange(uid, DEFAULT_NAME, false, now,
STATE_TYPE_PERMISSION);
}
@@ -131,44 +181,78 @@
}
}
+ private void handleOpChanged(int op, int uid, String packageName) {
+ if (DEBUG_PERMISSION_TRACKER) {
+ final IAppOpsService appOpsService = mInjector.getIAppOpsService();
+ try {
+ final int mode = appOpsService.checkOperation(op, uid, packageName);
+ Slog.i(TAG, "onOpChanged: " + opToPublicName(op)
+ + " " + UserHandle.formatUid(uid)
+ + " " + packageName + " " + mode);
+ } catch (RemoteException e) {
+ // Intra-process call, should never happen.
+ }
+ }
+ final Pair[] permissions = mInjector.getPolicy().getBgPermissionsInMonitor();
+ if (permissions != null && permissions.length > 0) {
+ for (int i = 0; i < permissions.length; i++) {
+ final Pair<String, Integer> pair = permissions[i];
+ if (pair.second != op) {
+ continue;
+ }
+ final UidGrantedPermissionState state =
+ new UidGrantedPermissionState(uid, pair.first, op);
+ synchronized (mLock) {
+ handlePermissionsChangedLocked(uid, new UidGrantedPermissionState[] {state});
+ }
+ break;
+ }
+ }
+ }
+
private void handlePermissionsChanged(int uid) {
- final String[] permissions = mInjector.getPolicy().getBgPermissionsInMonitor();
+ if (DEBUG_PERMISSION_TRACKER) {
+ Slog.i(TAG, "handlePermissionsChanged " + UserHandle.formatUid(uid));
+ }
+ final Pair[] permissions = mInjector.getPolicy().getBgPermissionsInMonitor();
if (permissions != null && permissions.length > 0) {
final PermissionManagerServiceInternal pm =
mInjector.getPermissionManagerServiceInternal();
- final boolean[] states = new boolean[permissions.length];
+ final UidGrantedPermissionState[] states =
+ new UidGrantedPermissionState[permissions.length];
for (int i = 0; i < permissions.length; i++) {
- states[i] = pm.checkUidPermission(uid, permissions[i]) == PERMISSION_GRANTED;
+ final Pair<String, Integer> pair = permissions[i];
+ states[i] = new UidGrantedPermissionState(uid, pair.first, pair.second);
if (DEBUG_PERMISSION_TRACKER) {
- Slog.i(TAG, UserHandle.formatUid(uid) + " " + permissions[i] + "=" + states[i]);
+ Slog.i(TAG, states[i].toString());
}
}
synchronized (mLock) {
- handlePermissionsChangedLocked(uid, permissions, states);
+ handlePermissionsChangedLocked(uid, states);
}
}
}
@GuardedBy("mLock")
- private void handlePermissionsChangedLocked(int uid, String[] permissions, boolean[] states) {
+ private void handlePermissionsChangedLocked(int uid, UidGrantedPermissionState[] states) {
final int index = mUidGrantedPermissionsInMonitor.indexOfKey(uid);
- ArraySet<String> grantedPermissions = index >= 0
+ ArraySet<UidGrantedPermissionState> grantedPermissions = index >= 0
? mUidGrantedPermissionsInMonitor.valueAt(index) : null;
final long now = SystemClock.elapsedRealtime();
- for (int i = 0; i < permissions.length; i++) {
- final String permission = permissions[i];
- final boolean granted = states[i];
+ for (int i = 0; i < states.length; i++) {
+ final boolean granted = states[i].isGranted();
boolean changed = false;
if (granted) {
if (grantedPermissions == null) {
grantedPermissions = new ArraySet<>();
mUidGrantedPermissionsInMonitor.put(uid, grantedPermissions);
+ changed = true;
}
- changed = grantedPermissions.add(permission);
- } else if (grantedPermissions != null) {
- changed = grantedPermissions.remove(permission);
- if (grantedPermissions.isEmpty()) {
+ grantedPermissions.add(states[i]);
+ } else if (grantedPermissions != null && !grantedPermissions.isEmpty()) {
+ if (grantedPermissions.remove(states[i]) && grantedPermissions.isEmpty()) {
mUidGrantedPermissionsInMonitor.removeAt(index);
+ changed = true;
}
}
if (changed) {
@@ -178,10 +262,141 @@
}
}
+ /**
+ * Represents the grant state of a permission + appop of the given UID.
+ */
+ private class UidGrantedPermissionState {
+ final int mUid;
+ final @Nullable String mPermission;
+ final int mAppOp;
+
+ private boolean mPermissionGranted;
+ private boolean mAppOpAllowed;
+
+ UidGrantedPermissionState(int uid, @Nullable String permission, int appOp) {
+ mUid = uid;
+ mPermission = permission;
+ mAppOp = appOp;
+ updatePermissionState();
+ updateAppOps();
+ }
+
+ void updatePermissionState() {
+ if (TextUtils.isEmpty(mPermission)) {
+ mPermissionGranted = true;
+ return;
+ }
+ mPermissionGranted = mInjector.getPermissionManagerServiceInternal()
+ .checkUidPermission(mUid, mPermission) == PERMISSION_GRANTED;
+ }
+
+ void updateAppOps() {
+ if (mAppOp == OP_NONE) {
+ mAppOpAllowed = true;
+ return;
+ }
+ final String[] packages = mInjector.getPackageManager().getPackagesForUid(mUid);
+ if (packages != null) {
+ final IAppOpsService appOpsService = mInjector.getIAppOpsService();
+ for (String pkg : packages) {
+ try {
+ final int mode = appOpsService.checkOperation(mAppOp, mUid, pkg);
+ if (mode == AppOpsManager.MODE_ALLOWED) {
+ mAppOpAllowed = true;
+ return;
+ }
+ } catch (RemoteException e) {
+ // Intra-process call, should never happen.
+ }
+ }
+ }
+ mAppOpAllowed = false;
+ }
+
+ boolean isGranted() {
+ return mPermissionGranted && mAppOpAllowed;
+ }
+
+ @Override
+ public boolean equals(Object other) {
+ if (other == null || !(other instanceof UidGrantedPermissionState)) {
+ return false;
+ }
+ final UidGrantedPermissionState otherState = (UidGrantedPermissionState) other;
+ return mUid == otherState.mUid && mAppOp == otherState.mAppOp
+ && Objects.equals(mPermission, otherState.mPermission);
+ }
+
+ @Override
+ public int hashCode() {
+ return (Integer.hashCode(mUid) * 31 + Integer.hashCode(mAppOp)) * 31
+ + (mPermission == null ? 0 : mPermission.hashCode());
+ }
+
+ @Override
+ public String toString() {
+ String s = "UidGrantedPermissionState{"
+ + System.identityHashCode(this) + " "
+ + UserHandle.formatUid(mUid) + ": ";
+ final boolean emptyPermissionName = TextUtils.isEmpty(mPermission);
+ if (!emptyPermissionName) {
+ s += mPermission + "=" + mPermissionGranted;
+ }
+ if (mAppOp != OP_NONE) {
+ if (!emptyPermissionName) {
+ s += ",";
+ }
+ s += opToPublicName(mAppOp) + "=" + mAppOpAllowed;
+ }
+ s += "}";
+ return s;
+ }
+ }
+
+ private void startWatchingMode(@NonNull Integer[] ops) {
+ synchronized (mAppOpsCallbacks) {
+ stopWatchingMode();
+ final IAppOpsService appOpsService = mInjector.getIAppOpsService();
+ try {
+ for (int op: ops) {
+ final MyAppOpsCallback cb = new MyAppOpsCallback();
+ mAppOpsCallbacks.put(op, cb);
+ appOpsService.startWatchingModeWithFlags(op, null,
+ AppOpsManager.WATCH_FOREGROUND_CHANGES, cb);
+ }
+ } catch (RemoteException e) {
+ // Intra-process call, should never happen.
+ }
+ }
+ }
+
+ private void stopWatchingMode() {
+ synchronized (mAppOpsCallbacks) {
+ final IAppOpsService appOpsService = mInjector.getIAppOpsService();
+ for (int i = mAppOpsCallbacks.size() - 1; i >= 0; i--) {
+ try {
+ appOpsService.stopWatchingMode(mAppOpsCallbacks.valueAt(i));
+ } catch (RemoteException e) {
+ // Intra-process call, should never happen.
+ }
+ }
+ mAppOpsCallbacks.clear();
+ }
+ }
+
+ private class MyAppOpsCallback extends IAppOpsCallback.Stub {
+ @Override
+ public void opChanged(int op, int uid, String packageName) {
+ mHandler.obtainMessage(MyHandler.MSG_APPOPS_CHANGED, op, uid, packageName)
+ .sendToTarget();
+ }
+ }
+
private static class MyHandler extends Handler {
static final int MSG_PERMISSIONS_INIT = 0;
static final int MSG_PERMISSIONS_DESTROY = 1;
static final int MSG_PERMISSIONS_CHANGED = 2;
+ static final int MSG_APPOPS_CHANGED = 3;
private @NonNull AppPermissionTracker mTracker;
@@ -194,14 +409,19 @@
public void handleMessage(Message msg) {
switch (msg.what) {
case MSG_PERMISSIONS_INIT:
+ mTracker.handleAppOpsInit();
mTracker.handlePermissionsInit();
break;
case MSG_PERMISSIONS_DESTROY:
mTracker.handlePermissionsDestroy();
+ mTracker.handleAppOpsDestroy();
break;
case MSG_PERMISSIONS_CHANGED:
mTracker.handlePermissionsChanged(msg.arg1);
break;
+ case MSG_APPOPS_CHANGED:
+ mTracker.handleOpChanged(msg.arg1, msg.arg2, (String) msg.obj);
+ break;
}
}
}
@@ -231,25 +451,41 @@
void dump(PrintWriter pw, String prefix) {
pw.print(prefix);
pw.println("APP PERMISSIONS TRACKER:");
- final String[] permissions = mInjector.getPolicy().getBgPermissionsInMonitor();
+ final Pair[] permissions = mInjector.getPolicy().getBgPermissionsInMonitor();
final String prefixMore = " " + prefix;
final String prefixMoreMore = " " + prefixMore;
- for (String permission : permissions) {
+ for (Pair<String, Integer> permission : permissions) {
pw.print(prefixMore);
- pw.print(permission);
+ final boolean emptyPermissionName = TextUtils.isEmpty(permission.first);
+ if (!emptyPermissionName) {
+ pw.print(permission.first);
+ }
+ if (permission.second != OP_NONE) {
+ if (!emptyPermissionName) {
+ pw.print('+');
+ }
+ pw.print(opToPublicName(permission.second));
+ }
pw.println(':');
synchronized (mLock) {
- final SparseArray<ArraySet<String>> uidPerms = mUidGrantedPermissionsInMonitor;
+ final SparseArray<ArraySet<UidGrantedPermissionState>> uidPerms =
+ mUidGrantedPermissionsInMonitor;
pw.print(prefixMoreMore);
pw.print('[');
boolean needDelimiter = false;
for (int i = 0, size = uidPerms.size(); i < size; i++) {
- if (uidPerms.valueAt(i).contains(permission)) {
- if (needDelimiter) {
- pw.print(',');
+ final ArraySet<UidGrantedPermissionState> uidPerm = uidPerms.valueAt(i);
+ for (int j = uidPerm.size() - 1; j >= 0; j--) {
+ final UidGrantedPermissionState state = uidPerm.valueAt(j);
+ if (state.mAppOp == permission.second
+ && TextUtils.equals(state.mPermission, permission.first)) {
+ if (needDelimiter) {
+ pw.print(',');
+ }
+ needDelimiter = true;
+ pw.print(UserHandle.formatUid(state.mUid));
+ break;
}
- needDelimiter = true;
- pw.print(UserHandle.formatUid(uidPerms.keyAt(i)));
}
}
pw.println(']');
@@ -277,20 +513,25 @@
static final boolean DEFAULT_BG_PERMISSION_MONITOR_ENABLED = true;
/**
- * Default value to {@link #mBgPermissionsInMonitor}.
+ * Default value to {@link #mBgPermissionsInMonitor}, it comes in pair;
+ * the first string strings in the pair is the permission name, and the second string
+ * is the appops name, if they are associated.
*/
static final String[] DEFAULT_BG_PERMISSIONS_IN_MONITOR = new String[] {
- ACCESS_FINE_LOCATION,
+ ACCESS_FINE_LOCATION, OPSTR_FINE_LOCATION,
+ CAMERA, OPSTR_CAMERA,
+ RECORD_AUDIO, OPSTR_RECORD_AUDIO,
};
/**
* @see #KEY_BG_PERMISSIONS_IN_MONITOR.
*/
- volatile String[] mBgPermissionsInMonitor = DEFAULT_BG_PERMISSIONS_IN_MONITOR;
+ volatile @NonNull Pair[] mBgPermissionsInMonitor;
AppPermissionPolicy(@NonNull Injector injector, @NonNull AppPermissionTracker tracker) {
super(injector, tracker, KEY_BG_PERMISSION_MONITOR_ENABLED,
DEFAULT_BG_PERMISSION_MONITOR_ENABLED);
+ mBgPermissionsInMonitor = parsePermissionConfig(DEFAULT_BG_PERMISSIONS_IN_MONITOR);
}
@Override
@@ -311,17 +552,38 @@
}
}
- String[] getBgPermissionsInMonitor() {
+ Pair[] getBgPermissionsInMonitor() {
return mBgPermissionsInMonitor;
}
+ private @NonNull Pair[] parsePermissionConfig(@NonNull String[] perms) {
+ final Pair[] result = new Pair[perms.length / 2];
+ for (int i = 0, j = 0; i < perms.length; i += 2, j++) {
+ try {
+ result[j] = Pair.create(TextUtils.isEmpty(perms[i]) ? null : perms[i],
+ TextUtils.isEmpty(perms[i + 1]) ? OP_NONE : strOpToOp(perms[i + 1]));
+ } catch (Exception e) {
+ // Ignore.
+ }
+ }
+ return result;
+ }
+
private void updateBgPermissionsInMonitor() {
final String config = DeviceConfig.getString(
DeviceConfig.NAMESPACE_ACTIVITY_MANAGER,
KEY_BG_PERMISSIONS_IN_MONITOR,
null);
- mBgPermissionsInMonitor = config != null
- ? config.split(",") : DEFAULT_BG_PERMISSIONS_IN_MONITOR;
+ final Pair[] newPermsInMonitor = parsePermissionConfig(
+ config != null ? config.split(",") : DEFAULT_BG_PERMISSIONS_IN_MONITOR);
+ if (!Arrays.equals(mBgPermissionsInMonitor, newPermsInMonitor)) {
+ mBgPermissionsInMonitor = newPermsInMonitor;
+ if (isEnabled()) {
+ // Trigger a reload.
+ onTrackerEnabled(false);
+ onTrackerEnabled(true);
+ }
+ }
}
@Override
@@ -338,7 +600,21 @@
pw.print(prefix);
pw.print(KEY_BG_PERMISSIONS_IN_MONITOR);
pw.print('=');
- pw.println(Arrays.toString(mBgPermissionsInMonitor));
+ pw.print('[');
+ for (int i = 0; i < mBgPermissionsInMonitor.length; i++) {
+ if (i > 0) {
+ pw.print(',');
+ }
+ final Pair<String, Integer> pair = mBgPermissionsInMonitor[i];
+ if (pair.first != null) {
+ pw.print(pair.first);
+ }
+ pw.print(',');
+ if (pair.second != OP_NONE) {
+ pw.print(opToPublicName(pair.second));
+ }
+ }
+ pw.println(']');
}
}
}
diff --git a/services/core/java/com/android/server/am/AppRestrictionController.java b/services/core/java/com/android/server/am/AppRestrictionController.java
index dc8403a..15484b2 100644
--- a/services/core/java/com/android/server/am/AppRestrictionController.java
+++ b/services/core/java/com/android/server/am/AppRestrictionController.java
@@ -135,6 +135,7 @@
import android.util.SparseArray;
import android.util.SparseArrayMap;
import android.util.TimeUtils;
+import android.util.proto.ProtoOutputStream;
import com.android.internal.annotations.GuardedBy;
import com.android.internal.annotations.VisibleForTesting;
@@ -1369,6 +1370,12 @@
}
}
+ void dumpAsProto(ProtoOutputStream proto, int uid) {
+ for (int i = 0, size = mAppStateTrackers.size(); i < size; i++) {
+ mAppStateTrackers.get(i).dumpAsProto(proto, uid);
+ }
+ }
+
private void applyRestrictionLevel(String pkgName, int uid, @RestrictionLevel int level,
int curBucket, boolean allowUpdateBucket, int reason, int subReason) {
int curLevel;
diff --git a/services/core/java/com/android/server/am/BaseAppStateTracker.java b/services/core/java/com/android/server/am/BaseAppStateTracker.java
index 0fada53..2f76e24 100644
--- a/services/core/java/com/android/server/am/BaseAppStateTracker.java
+++ b/services/core/java/com/android/server/am/BaseAppStateTracker.java
@@ -33,9 +33,12 @@
import android.os.BatteryManagerInternal;
import android.os.BatteryStatsInternal;
import android.os.Handler;
+import android.os.ServiceManager;
import android.permission.PermissionManager;
import android.util.Slog;
+import android.util.proto.ProtoOutputStream;
+import com.android.internal.app.IAppOpsService;
import com.android.server.DeviceIdleInternal;
import com.android.server.LocalServices;
import com.android.server.notification.NotificationManagerInternal;
@@ -61,13 +64,15 @@
static final int STATE_TYPE_MEDIA_SESSION = 1;
static final int STATE_TYPE_FGS_MEDIA_PLAYBACK = 1 << 1;
static final int STATE_TYPE_FGS_LOCATION = 1 << 2;
- static final int STATE_TYPE_PERMISSION = 1 << 3;
- static final int STATE_TYPE_NUM = 4;
+ static final int STATE_TYPE_FGS_WITH_NOTIFICATION = 1 << 3;
+ static final int STATE_TYPE_PERMISSION = 1 << 4;
+ static final int STATE_TYPE_NUM = 5;
static final int STATE_TYPE_INDEX_MEDIA_SESSION = 0;
static final int STATE_TYPE_INDEX_FGS_MEDIA_PLAYBACK = 1;
static final int STATE_TYPE_INDEX_FGS_LOCATION = 2;
- static final int STATE_TYPE_INDEX_PERMISSION = 3;
+ static final int STATE_TYPE_INDEX_FGS_WITH_NOTIFICATION = 3;
+ static final int STATE_TYPE_INDEX_PERMISSION = 4;
protected final AppRestrictionController mAppRestrictionController;
protected final Injector<T> mInjector;
@@ -126,6 +131,9 @@
case STATE_TYPE_FGS_LOCATION:
sb.append("FGS_LOCATION");
break;
+ case STATE_TYPE_FGS_WITH_NOTIFICATION:
+ sb.append("FGS_NOTIFICATION");
+ break;
case STATE_TYPE_PERMISSION:
sb.append("PERMISSION");
break;
@@ -250,6 +258,9 @@
mInjector.getPolicy().dump(pw, " " + prefix);
}
+ void dumpAsProto(ProtoOutputStream proto, int uid) {
+ }
+
static class Injector<T extends BaseAppStatePolicy> {
T mAppStatePolicy;
@@ -266,6 +277,7 @@
MediaSessionManager mMediaSessionManager;
RoleManager mRoleManager;
NotificationManagerInternal mNotificationManagerInternal;
+ IAppOpsService mIAppOpsService;
void setPolicy(T policy) {
mAppStatePolicy = policy;
@@ -288,6 +300,8 @@
mRoleManager = context.getSystemService(RoleManager.class);
mNotificationManagerInternal = LocalServices.getService(
NotificationManagerInternal.class);
+ mIAppOpsService = IAppOpsService.Stub.asInterface(
+ ServiceManager.getService(Context.APP_OPS_SERVICE));
getPolicy().onSystemReady();
}
@@ -358,5 +372,9 @@
NotificationManagerInternal getNotificationManagerInternal() {
return mNotificationManagerInternal;
}
+
+ IAppOpsService getIAppOpsService() {
+ return mIAppOpsService;
+ }
}
}
diff --git a/services/core/java/com/android/server/am/BatteryExternalStatsWorker.java b/services/core/java/com/android/server/am/BatteryExternalStatsWorker.java
index 1131fa8..4fdc88d 100644
--- a/services/core/java/com/android/server/am/BatteryExternalStatsWorker.java
+++ b/services/core/java/com/android/server/am/BatteryExternalStatsWorker.java
@@ -561,8 +561,18 @@
// We were asked to fetch Bluetooth data.
final BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter();
if (adapter != null) {
- bluetoothReceiver = new SynchronousResultReceiver("bluetooth");
- adapter.requestControllerActivityEnergyInfo(bluetoothReceiver);
+ SynchronousResultReceiver resultReceiver =
+ new SynchronousResultReceiver("bluetooth");
+ adapter.requestControllerActivityEnergyInfo(
+ Runnable::run,
+ info -> {
+ Bundle bundle = new Bundle();
+ bundle.putParcelable(BatteryStats.RESULT_RECEIVER_CONTROLLER_KEY,
+ info);
+ resultReceiver.send(0, bundle);
+ }
+ );
+ bluetoothReceiver = resultReceiver;
}
}
diff --git a/services/core/java/com/android/server/am/OomAdjuster.java b/services/core/java/com/android/server/am/OomAdjuster.java
index 7ed3dcf..9626bbe 100644
--- a/services/core/java/com/android/server/am/OomAdjuster.java
+++ b/services/core/java/com/android/server/am/OomAdjuster.java
@@ -407,7 +407,6 @@
uids.clear();
uids.put(uidRec.getUid(), uidRec);
updateUidsLSP(uids, SystemClock.elapsedRealtime());
- mProcessList.incrementProcStateSeqAndNotifyAppsLOSP(uids);
}
}
@@ -1144,8 +1143,6 @@
}
}
- mProcessList.incrementProcStateSeqAndNotifyAppsLOSP(activeUids);
-
return mService.mAppProfiler.updateLowMemStateLSP(numCached, numEmpty, numTrimming);
}
@@ -1180,6 +1177,11 @@
@GuardedBy({"mService", "mProcLock"})
private void updateUidsLSP(ActiveUids activeUids, final long nowElapsed) {
+ // This compares previously set procstate to the current procstate in regards to whether
+ // or not the app's network access will be blocked. So, this needs to be called before
+ // we update the UidRecord's procstate by calling {@link UidRecord#setSetProcState}.
+ mProcessList.incrementProcStateSeqAndNotifyAppsLOSP(activeUids);
+
ArrayList<UidRecord> becameIdle = mTmpBecameIdle;
becameIdle.clear();
diff --git a/services/core/java/com/android/server/ambientcontext/AmbientContextManagerPerUserService.java b/services/core/java/com/android/server/ambientcontext/AmbientContextManagerPerUserService.java
index b73cf5b..42a7423 100644
--- a/services/core/java/com/android/server/ambientcontext/AmbientContextManagerPerUserService.java
+++ b/services/core/java/com/android/server/ambientcontext/AmbientContextManagerPerUserService.java
@@ -171,16 +171,15 @@
return;
}
- // Remove any existing intent and unregister for this package before adding a new one.
+ // Remove any existing PendingIntent for this package.
String callingPackage = pendingIntent.getCreatorPackage();
PendingIntent duplicatePendingIntent = findExistingRequestByPackage(callingPackage);
if (duplicatePendingIntent != null) {
- Slog.d(TAG, "Unregister duplicate request from " + callingPackage);
- onUnregisterObserver(callingPackage);
+ Slog.d(TAG, "Replace duplicate request from " + callingPackage);
mExistingPendingIntents.remove(duplicatePendingIntent);
}
- // Register new package and add request to mExistingRequests
+ // Register package and add pendingIntent to mExistingPendingIntents
startDetection(request, callingPackage, createDetectionResultRemoteCallback(),
getServerStatusCallback(clientStatusCallback));
mExistingPendingIntents.add(pendingIntent);
diff --git a/services/core/java/com/android/server/ambientcontext/AmbientContextShellCommand.java b/services/core/java/com/android/server/ambientcontext/AmbientContextShellCommand.java
index 010bf1b..e2b22dc 100644
--- a/services/core/java/com/android/server/ambientcontext/AmbientContextShellCommand.java
+++ b/services/core/java/com/android/server/ambientcontext/AmbientContextShellCommand.java
@@ -110,6 +110,8 @@
return runStopDetection();
case "get-last-status-code":
return getLastStatusCode();
+ case "get-last-package-name":
+ return getLastPackageName();
case "query-service-status":
return runQueryServiceStatus();
case "get-bound-package":
@@ -157,6 +159,13 @@
return lastResponse.getStatusCode();
}
+ private int getLastPackageName() {
+ AmbientContextDetectionServiceStatus lastResponse =
+ sTestableCallbackInternal.getLastStatus();
+ out.println(lastResponse == null ? "" : lastResponse.getPackageName());
+ return 0;
+ }
+
@Override
public void onHelp() {
PrintWriter pw = getOutPrintWriter();
@@ -167,6 +176,7 @@
pw.println(" start-detection USER_ID PACKAGE_NAME: Starts AmbientContextEvent detection.");
pw.println(" stop-detection USER_ID: Stops AmbientContextEvent detection.");
pw.println(" get-last-status-code: Prints the latest request status code.");
+ pw.println(" get-last-package-name: Prints the latest request package name.");
pw.println(" query-event-status USER_ID PACKAGE_NAME: Prints the event status code.");
pw.println(" get-bound-package USER_ID:"
+ " Print the bound package that implements the service.");
diff --git a/services/core/java/com/android/server/app/GameServiceProviderInstanceImpl.java b/services/core/java/com/android/server/app/GameServiceProviderInstanceImpl.java
index e920523..b38195a 100644
--- a/services/core/java/com/android/server/app/GameServiceProviderInstanceImpl.java
+++ b/services/core/java/com/android/server/app/GameServiceProviderInstanceImpl.java
@@ -85,15 +85,6 @@
Slog.w(TAG, "Failed to send connected event", ex);
}
}
-
- @Override
- public void onDisconnected(@NonNull IGameService service) {
- try {
- service.disconnected();
- } catch (RemoteException ex) {
- Slog.w(TAG, "Failed to send disconnected event", ex);
- }
- }
};
private final ServiceLifecycleCallbacks<IGameSessionService>
@@ -181,7 +172,8 @@
}
@Override
- public void onForegroundServicesChanged(int pid, int uid, int serviceTypes) {}
+ public void onForegroundServicesChanged(int pid, int uid, int serviceTypes) {
+ }
};
private final IGameServiceController mGameServiceController =
@@ -200,8 +192,11 @@
private final IGameSessionController mGameSessionController =
new IGameSessionController.Stub() {
@Override
+ @RequiresPermission(android.Manifest.permission.MANAGE_GAME_ACTIVITY)
public void takeScreenshot(int taskId,
@NonNull AndroidFuture gameScreenshotResultFuture) {
+ mContext.enforceCallingPermission(Manifest.permission.MANAGE_GAME_ACTIVITY,
+ "takeScreenshot()");
mBackgroundExecutor.execute(() -> {
GameServiceProviderInstanceImpl.this.takeScreenshot(taskId,
gameScreenshotResultFuture);
@@ -338,7 +333,9 @@
destroyAndClearAllGameSessionsLocked();
- mGameServiceConnector.unbind();
+ mGameServiceConnector.post(IGameService::disconnected).whenComplete((result, t) -> {
+ mGameServiceConnector.unbind();
+ });
mGameSessionServiceConnector.unbind();
mGameServiceConnector.setServiceLifecycleCallbacks(null);
diff --git a/services/core/java/com/android/server/attention/AttentionManagerService.java b/services/core/java/com/android/server/attention/AttentionManagerService.java
index 567d1ae..d16fe12 100644
--- a/services/core/java/com/android/server/attention/AttentionManagerService.java
+++ b/services/core/java/com/android/server/attention/AttentionManagerService.java
@@ -74,6 +74,8 @@
import java.io.PrintWriter;
import java.util.Objects;
import java.util.Set;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
/**
* An attention service implementation that runs in System Server process.
@@ -87,6 +89,9 @@
/** Service will unbind if connection is not used for that amount of time. */
private static final long CONNECTION_TTL_MILLIS = 60_000;
+ /** How long AttentionManagerService will wait for service binding after lazy binding. */
+ private static final long SERVICE_BINDING_WAIT_MILLIS = 1000;
+
/** DeviceConfig flag name, if {@code true}, enables AttentionManagerService features. */
@VisibleForTesting
static final String KEY_SERVICE_ENABLED = "service_enabled";
@@ -129,6 +134,7 @@
@GuardedBy("mLock")
private boolean mBinding;
private AttentionHandler mAttentionHandler;
+ private CountDownLatch mServiceBindingLatch;
@VisibleForTesting
ComponentName mComponentName;
@@ -161,6 +167,7 @@
mLock = lock;
mAttentionHandler = handler;
mPrivacyManager = SensorPrivacyManager.getInstance(context);
+ mServiceBindingLatch = new CountDownLatch(1);
}
@Override
@@ -275,13 +282,16 @@
}
synchronized (mLock) {
- final long now = SystemClock.uptimeMillis();
// schedule shutting down the connection if no one resets this timer
freeIfInactiveLocked();
// lazily start the service, which should be very lightweight to start
bindLocked();
-
+ }
+ final long now = SystemClock.uptimeMillis();
+ // Proceed when the service binding is complete.
+ awaitServiceBinding(Math.min(SERVICE_BINDING_WAIT_MILLIS, timeout));
+ synchronized (mLock) {
// throttle frequent requests
final AttentionCheckCache cache = mAttentionCheckCacheBuffer == null ? null
: mAttentionCheckCacheBuffer.getLast();
@@ -361,7 +371,10 @@
// lazily start the service, which should be very lightweight to start
bindLocked();
-
+ }
+ // Proceed when the service binding is complete.
+ awaitServiceBinding(SERVICE_BINDING_WAIT_MILLIS);
+ synchronized (mLock) {
/*
Prevent spamming with multiple requests, only one at a time is allowed.
If there are use-cases for keeping track of multiple requests, we
@@ -419,6 +432,14 @@
return context.getPackageManager().getAttentionServicePackageName();
}
+ private void awaitServiceBinding(long millis) {
+ try {
+ mServiceBindingLatch.await(millis, TimeUnit.MILLISECONDS);
+ } catch (InterruptedException e) {
+ Slog.e(LOG_TAG, "Interrupted while waiting to bind Attention Service.", e);
+ }
+ }
+
/**
* Provides attention service component name at runtime, making sure it's provided by the
* system.
@@ -711,6 +732,7 @@
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
init(IAttentionService.Stub.asInterface(service));
+ mServiceBindingLatch.countDown();
}
@Override
@@ -730,6 +752,7 @@
void cleanupService() {
init(null);
+ mServiceBindingLatch = new CountDownLatch(1);
}
private void init(@Nullable IAttentionService service) {
diff --git a/services/core/java/com/android/server/audio/AudioService.java b/services/core/java/com/android/server/audio/AudioService.java
index d01be58..309a4ff 100644
--- a/services/core/java/com/android/server/audio/AudioService.java
+++ b/services/core/java/com/android/server/audio/AudioService.java
@@ -102,6 +102,7 @@
import android.media.IRingtonePlayer;
import android.media.ISpatializerCallback;
import android.media.ISpatializerHeadToSoundStagePoseCallback;
+import android.media.ISpatializerHeadTrackerAvailableCallback;
import android.media.ISpatializerHeadTrackingModeCallback;
import android.media.ISpatializerOutputCallback;
import android.media.IStrategyPreferredDevicesDispatcher;
@@ -8723,6 +8724,11 @@
return mSpatializerHelper.isHeadTrackerEnabled(Objects.requireNonNull(device));
}
+ /** @see Spatializer#isHeadTrackerAvailable() */
+ public boolean isHeadTrackerAvailable() {
+ return mSpatializerHelper.isHeadTrackerAvailable();
+ }
+
/** @see Spatializer#setSpatializerEnabled(boolean) */
public void setSpatializerEnabled(boolean enabled) {
enforceModifyDefaultAudioEffectsPermission();
@@ -8767,6 +8773,13 @@
mSpatializerHelper.unregisterHeadTrackingModeCallback(cb);
}
+ /** @see Spatializer.SpatializerHeadTrackerAvailableDispatcherStub */
+ public void registerSpatializerHeadTrackerAvailableCallback(
+ @NonNull ISpatializerHeadTrackerAvailableCallback cb, boolean register) {
+ Objects.requireNonNull(cb);
+ mSpatializerHelper.registerHeadTrackerAvailableCallback(cb, register);
+ }
+
/** @see Spatializer#setOnHeadToSoundstagePoseUpdatedListener */
public void registerHeadToSoundstagePoseCallback(
@NonNull ISpatializerHeadToSoundStagePoseCallback cb) {
diff --git a/services/core/java/com/android/server/audio/SpatializerHelper.java b/services/core/java/com/android/server/audio/SpatializerHelper.java
index 193cc5f..f0f04e2 100644
--- a/services/core/java/com/android/server/audio/SpatializerHelper.java
+++ b/services/core/java/com/android/server/audio/SpatializerHelper.java
@@ -30,6 +30,7 @@
import android.media.ISpatializer;
import android.media.ISpatializerCallback;
import android.media.ISpatializerHeadToSoundStagePoseCallback;
+import android.media.ISpatializerHeadTrackerAvailableCallback;
import android.media.ISpatializerHeadTrackingCallback;
import android.media.ISpatializerHeadTrackingModeCallback;
import android.media.ISpatializerOutputCallback;
@@ -126,6 +127,7 @@
private boolean mBinauralSupported = false;
private int mActualHeadTrackingMode = Spatializer.HEAD_TRACKING_MODE_UNSUPPORTED;
private int mDesiredHeadTrackingMode = Spatializer.HEAD_TRACKING_MODE_RELATIVE_WORLD;
+ private boolean mHeadTrackerAvailable = false;
/**
* The desired head tracking mode when enabling head tracking, tracks mDesiredHeadTrackingMode,
* except when head tracking gets disabled through setting the desired mode to
@@ -137,6 +139,7 @@
private @Nullable SpatializerCallback mSpatCallback;
private @Nullable SpatializerHeadTrackingCallback mSpatHeadTrackingCallback;
private @Nullable HelperDynamicSensorCallback mDynSensorCallback;
+ private boolean mIsHeadTrackingSupported = false;
// default attributes and format that determine basic availability of spatialization
private static final AudioAttributes DEFAULT_ATTRIBUTES = new AudioAttributes.Builder()
@@ -275,6 +278,7 @@
*/
synchronized void reset(boolean featureEnabled) {
Log.i(TAG, "Resetting");
+ releaseSpat();
mState = STATE_UNINITIALIZED;
mSpatLevel = Spatializer.SPATIALIZER_IMMERSIVE_LEVEL_NONE;
mCapableSpatLevel = Spatializer.SPATIALIZER_IMMERSIVE_LEVEL_NONE;
@@ -810,8 +814,9 @@
mSpat = AudioSystem.getSpatializer(mSpatCallback);
try {
mSpat.setLevel((byte) Spatializer.SPATIALIZER_IMMERSIVE_LEVEL_MULTICHANNEL);
+ mIsHeadTrackingSupported = mSpat.isHeadTrackingSupported();
//TODO: register heatracking callback only when sensors are registered
- if (mSpat.isHeadTrackingSupported()) {
+ if (mIsHeadTrackingSupported) {
mSpat.registerHeadTrackingCallback(mSpatHeadTrackingCallback);
}
} catch (RemoteException e) {
@@ -829,12 +834,16 @@
if (mSpat != null) {
mSpatCallback = null;
try {
- mSpat.registerHeadTrackingCallback(null);
+ if (mIsHeadTrackingSupported) {
+ mSpat.registerHeadTrackingCallback(null);
+ }
+ mHeadTrackerAvailable = false;
mSpat.release();
- mSpat = null;
} catch (RemoteException e) {
Log.e(TAG, "Can't set release spatializer cleanly", e);
}
+ mIsHeadTrackingSupported = false;
+ mSpat = null;
}
}
@@ -889,6 +898,18 @@
mHeadTrackingModeCallbacks.unregister(callback);
}
+ final RemoteCallbackList<ISpatializerHeadTrackerAvailableCallback> mHeadTrackerCallbacks =
+ new RemoteCallbackList<>();
+
+ synchronized void registerHeadTrackerAvailableCallback(
+ @NonNull ISpatializerHeadTrackerAvailableCallback cb, boolean register) {
+ if (register) {
+ mHeadTrackerCallbacks.register(cb);
+ } else {
+ mHeadTrackerCallbacks.unregister(cb);
+ }
+ }
+
synchronized int[] getSupportedHeadTrackingModes() {
switch (mState) {
case STATE_UNINITIALIZED:
@@ -1089,6 +1110,10 @@
return false;
}
+ synchronized boolean isHeadTrackerAvailable() {
+ return mHeadTrackerAvailable;
+ }
+
private boolean checkSpatForHeadTracking(String funcName) {
switch (mState) {
case STATE_UNINITIALIZED:
@@ -1104,7 +1129,7 @@
}
break;
}
- return true;
+ return mIsHeadTrackingSupported;
}
private void dispatchActualHeadTrackingMode(int newMode) {
@@ -1114,7 +1139,8 @@
mHeadTrackingModeCallbacks.getBroadcastItem(i)
.dispatchSpatializerActualHeadTrackingModeChanged(newMode);
} catch (RemoteException e) {
- Log.e(TAG, "Error in dispatchSpatializerActualHeadTrackingModeChanged", e);
+ Log.e(TAG, "Error in dispatchSpatializerActualHeadTrackingModeChanged("
+ + newMode + ")", e);
}
}
mHeadTrackingModeCallbacks.finishBroadcast();
@@ -1127,12 +1153,27 @@
mHeadTrackingModeCallbacks.getBroadcastItem(i)
.dispatchSpatializerDesiredHeadTrackingModeChanged(newMode);
} catch (RemoteException e) {
- Log.e(TAG, "Error in dispatchSpatializerDesiredHeadTrackingModeChanged", e);
+ Log.e(TAG, "Error in dispatchSpatializerDesiredHeadTrackingModeChanged("
+ + newMode + ")", e);
}
}
mHeadTrackingModeCallbacks.finishBroadcast();
}
+ private void dispatchHeadTrackerAvailable(boolean available) {
+ final int nbCallbacks = mHeadTrackerCallbacks.beginBroadcast();
+ for (int i = 0; i < nbCallbacks; i++) {
+ try {
+ mHeadTrackerCallbacks.getBroadcastItem(i)
+ .dispatchSpatializerHeadTrackerAvailable(available);
+ } catch (RemoteException e) {
+ Log.e(TAG, "Error in dispatchSpatializerHeadTrackerAvailable("
+ + available + ")", e);
+ }
+ }
+ mHeadTrackerCallbacks.finishBroadcast();
+ }
+
//------------------------------------------------------
// head pose
final RemoteCallbackList<ISpatializerHeadToSoundStagePoseCallback> mHeadPoseCallbacks =
@@ -1278,13 +1319,8 @@
Log.e(TAG, "not " + action + " sensors, null spatializer");
return;
}
- try {
- if (!mSpat.isHeadTrackingSupported()) {
- Log.e(TAG, "not " + action + " sensors, spatializer doesn't support headtracking");
- return;
- }
- } catch (RemoteException e) {
- Log.e(TAG, "not " + action + " sensors, error querying headtracking", e);
+ if (!mIsHeadTrackingSupported) {
+ Log.e(TAG, "not " + action + " sensors, spatializer doesn't support headtracking");
return;
}
int headHandle = -1;
@@ -1347,6 +1383,10 @@
try {
Log.i(TAG, "setHeadSensor:" + headHandle);
mSpat.setHeadSensor(headHandle);
+ if (mHeadTrackerAvailable != (headHandle != -1)) {
+ mHeadTrackerAvailable = (headHandle != -1);
+ dispatchHeadTrackerAvailable(mHeadTrackerAvailable);
+ }
} catch (Exception e) {
Log.e(TAG, "Error calling setHeadSensor:" + headHandle, e);
}
diff --git a/services/core/java/com/android/server/biometrics/sensors/BaseClientMonitor.java b/services/core/java/com/android/server/biometrics/sensors/BaseClientMonitor.java
index 1b2e606..1370fd8 100644
--- a/services/core/java/com/android/server/biometrics/sensors/BaseClientMonitor.java
+++ b/services/core/java/com/android/server/biometrics/sensors/BaseClientMonitor.java
@@ -38,7 +38,7 @@
*/
public abstract class BaseClientMonitor implements IBinder.DeathRecipient {
- private static final String TAG = "Biometrics/ClientMonitor";
+ private static final String TAG = "BaseClientMonitor";
protected static final boolean DEBUG = true;
// Counter used to distinguish between ClientMonitor instances to help debugging.
@@ -120,8 +120,18 @@
}
/**
+ * Sets the lifecycle callback before the operation is started via
+ * {@link #start(ClientMonitorCallback)} when the client must wait for a cookie before starting.
+ *
+ * @param callback lifecycle callback (typically same callback used for starting the operation)
+ */
+ public void waitForCookie(@NonNull ClientMonitorCallback callback) {
+ mCallback = callback;
+ }
+
+ /**
* Starts the ClientMonitor's lifecycle.
- * @param callback invoked when the operation is complete (succeeds, fails, etc)
+ * @param callback invoked when the operation is complete (succeeds, fails, etc.)
*/
public void start(@NonNull ClientMonitorCallback callback) {
mCallback = wrapCallbackForStart(callback);
@@ -246,12 +256,12 @@
}
/** Unique request id. */
- public final long getRequestId() {
+ public long getRequestId() {
return mRequestId;
}
/** If a unique id has been set via {@link #setRequestId(long)} */
- public final boolean hasRequestId() {
+ public boolean hasRequestId() {
return mRequestId > 0;
}
diff --git a/services/core/java/com/android/server/biometrics/sensors/BiometricScheduler.java b/services/core/java/com/android/server/biometrics/sensors/BiometricScheduler.java
index d0ec447..19a93f3 100644
--- a/services/core/java/com/android/server/biometrics/sensors/BiometricScheduler.java
+++ b/services/core/java/com/android/server/biometrics/sensors/BiometricScheduler.java
@@ -285,7 +285,7 @@
// Not all operations start immediately. BiometricPrompt waits for its operation
// to arrive at the head of the queue, before pinging it to start.
- final int cookie = mCurrentOperation.isReadyToStart();
+ final int cookie = mCurrentOperation.isReadyToStart(mInternalCallback);
if (cookie == 0) {
if (!mCurrentOperation.start(mInternalCallback)) {
// Note down current length of queue
@@ -463,6 +463,18 @@
return mCurrentOperation != null ? mCurrentOperation.getClientMonitor() : null;
}
+ /** The current operation if the requestId is set and matches. */
+ @Deprecated
+ @Nullable
+ public BaseClientMonitor getCurrentClientIfMatches(long requestId) {
+ if (mCurrentOperation != null) {
+ if (mCurrentOperation.isMatchingRequestId(requestId)) {
+ return mCurrentOperation.getClientMonitor();
+ }
+ }
+ return null;
+ }
+
public int getCurrentPendingCount() {
return mPendingOperations.size();
}
diff --git a/services/core/java/com/android/server/biometrics/sensors/BiometricSchedulerOperation.java b/services/core/java/com/android/server/biometrics/sensors/BiometricSchedulerOperation.java
index 15f0cad..968146a 100644
--- a/services/core/java/com/android/server/biometrics/sensors/BiometricSchedulerOperation.java
+++ b/services/core/java/com/android/server/biometrics/sensors/BiometricSchedulerOperation.java
@@ -123,11 +123,12 @@
*
* @return cookie or 0 if ready/started
*/
- public int isReadyToStart() {
+ public int isReadyToStart(@NonNull ClientMonitorCallback callback) {
if (mState == STATE_WAITING_FOR_COOKIE || mState == STATE_WAITING_IN_QUEUE) {
final int cookie = mClientMonitor.getCookie();
if (cookie != 0) {
mState = STATE_WAITING_FOR_COOKIE;
+ mClientMonitor.waitForCookie(getWrappedCallback(callback));
}
return cookie;
}
@@ -137,7 +138,7 @@
/**
* Start this operation without waiting for a cookie
- * (i.e. {@link #isReadyToStart() returns zero}
+ * (i.e. {@link #isReadyToStart(ClientMonitorCallback)} returns zero}
*
* @param callback lifecycle callback
* @return if this operation started
diff --git a/services/core/java/com/android/server/biometrics/sensors/SensorOverlays.java b/services/core/java/com/android/server/biometrics/sensors/SensorOverlays.java
index 0087178..aeb6b6e 100644
--- a/services/core/java/com/android/server/biometrics/sensors/SensorOverlays.java
+++ b/services/core/java/com/android/server/biometrics/sensors/SensorOverlays.java
@@ -84,7 +84,8 @@
};
try {
- mUdfpsOverlayController.get().showUdfpsOverlay(sensorId, reason, callback);
+ mUdfpsOverlayController.get().showUdfpsOverlay(
+ client.getRequestId(), sensorId, reason, callback);
} catch (RemoteException e) {
Slog.e(TAG, "Remote exception when showing the UDFPS overlay", e);
}
diff --git a/services/core/java/com/android/server/biometrics/sensors/UserAwareBiometricScheduler.java b/services/core/java/com/android/server/biometrics/sensors/UserAwareBiometricScheduler.java
index 4f90020..a099977 100644
--- a/services/core/java/com/android/server/biometrics/sensors/UserAwareBiometricScheduler.java
+++ b/services/core/java/com/android/server/biometrics/sensors/UserAwareBiometricScheduler.java
@@ -57,30 +57,25 @@
@Nullable private StopUserClient<?> mStopUserClient;
private class ClientFinishedCallback implements ClientMonitorCallback {
- private final BaseClientMonitor mOwner;
+ @NonNull private final BaseClientMonitor mOwner;
- ClientFinishedCallback(BaseClientMonitor owner) {
+ ClientFinishedCallback(@NonNull BaseClientMonitor owner) {
mOwner = owner;
}
@Override
public void onClientFinished(@NonNull BaseClientMonitor clientMonitor, boolean success) {
mHandler.post(() -> {
- if (mOwner != clientMonitor) {
- Slog.e(getTag(), "[Wrong client finished], actual: "
- + clientMonitor + ", expected: " + mOwner);
- return;
- }
-
Slog.d(getTag(), "[Client finished] " + clientMonitor + ", success: " + success);
if (mCurrentOperation != null && mCurrentOperation.isFor(mOwner)) {
mCurrentOperation = null;
- startNextOperationIfIdle();
} else {
- // can usually be ignored (hal died, etc.)
- Slog.d(getTag(), "operation is already null or different (reset?): "
+ // can happen if the hal dies and is usually okay
+ // do not unset the current operation that may be newer
+ Slog.w(getTag(), "operation is already null or different (reset?): "
+ mCurrentOperation);
}
+ startNextOperationIfIdle();
});
}
}
diff --git a/services/core/java/com/android/server/biometrics/sensors/face/aidl/FaceAuthenticationClient.java b/services/core/java/com/android/server/biometrics/sensors/face/aidl/FaceAuthenticationClient.java
index 7765ab3..9ae6750 100644
--- a/services/core/java/com/android/server/biometrics/sensors/face/aidl/FaceAuthenticationClient.java
+++ b/services/core/java/com/android/server/biometrics/sensors/face/aidl/FaceAuthenticationClient.java
@@ -136,8 +136,8 @@
try {
if (mSensorPrivacyManager != null
&& mSensorPrivacyManager
- .isSensorPrivacyEnabled(SensorPrivacyManager.Sensors.CAMERA,
- getTargetUserId())) {
+ .isSensorPrivacyEnabled(SensorPrivacyManager.TOGGLE_TYPE_SOFTWARE,
+ SensorPrivacyManager.Sensors.CAMERA)) {
onError(BiometricConstants.BIOMETRIC_ERROR_HW_UNAVAILABLE,
0 /* vendorCode */);
mCallback.onClientFinished(this, false /* success */);
diff --git a/services/core/java/com/android/server/biometrics/sensors/face/aidl/FaceDetectClient.java b/services/core/java/com/android/server/biometrics/sensors/face/aidl/FaceDetectClient.java
index efedcf8..ded1810 100644
--- a/services/core/java/com/android/server/biometrics/sensors/face/aidl/FaceDetectClient.java
+++ b/services/core/java/com/android/server/biometrics/sensors/face/aidl/FaceDetectClient.java
@@ -96,7 +96,8 @@
protected void startHalOperation() {
if (mSensorPrivacyManager != null
&& mSensorPrivacyManager
- .isSensorPrivacyEnabled(SensorPrivacyManager.Sensors.CAMERA, getTargetUserId())) {
+ .isSensorPrivacyEnabled(SensorPrivacyManager.TOGGLE_TYPE_SOFTWARE,
+ SensorPrivacyManager.Sensors.CAMERA)) {
onError(BiometricConstants.BIOMETRIC_ERROR_HW_UNAVAILABLE, 0 /* vendorCode */);
mCallback.onClientFinished(this, false /* success */);
return;
diff --git a/services/core/java/com/android/server/biometrics/sensors/face/hidl/FaceAuthenticationClient.java b/services/core/java/com/android/server/biometrics/sensors/face/hidl/FaceAuthenticationClient.java
index 8d76e9f..1935a5b 100644
--- a/services/core/java/com/android/server/biometrics/sensors/face/hidl/FaceAuthenticationClient.java
+++ b/services/core/java/com/android/server/biometrics/sensors/face/hidl/FaceAuthenticationClient.java
@@ -109,7 +109,8 @@
if (mSensorPrivacyManager != null
&& mSensorPrivacyManager
- .isSensorPrivacyEnabled(SensorPrivacyManager.Sensors.CAMERA, getTargetUserId())) {
+ .isSensorPrivacyEnabled(SensorPrivacyManager.TOGGLE_TYPE_SOFTWARE,
+ SensorPrivacyManager.Sensors.CAMERA)) {
onError(BiometricFaceConstants.FACE_ERROR_HW_UNAVAILABLE, 0 /* vendorCode */);
mCallback.onClientFinished(this, false /* success */);
return;
diff --git a/services/core/java/com/android/server/biometrics/sensors/fingerprint/FingerprintService.java b/services/core/java/com/android/server/biometrics/sensors/fingerprint/FingerprintService.java
index b4befd2..e8d8fb8 100644
--- a/services/core/java/com/android/server/biometrics/sensors/fingerprint/FingerprintService.java
+++ b/services/core/java/com/android/server/biometrics/sensors/fingerprint/FingerprintService.java
@@ -928,7 +928,8 @@
}
@Override
- public void onPointerDown(int sensorId, int x, int y, float minor, float major) {
+ public void onPointerDown(long requestId, int sensorId, int x, int y,
+ float minor, float major) {
Utils.checkPermission(getContext(), USE_BIOMETRIC_INTERNAL);
final ServiceProvider provider = getProviderForSensor(sensorId);
@@ -936,11 +937,11 @@
Slog.w(TAG, "No matching provider for onFingerDown, sensorId: " + sensorId);
return;
}
- provider.onPointerDown(sensorId, x, y, minor, major);
+ provider.onPointerDown(requestId, sensorId, x, y, minor, major);
}
@Override
- public void onPointerUp(int sensorId) {
+ public void onPointerUp(long requestId, int sensorId) {
Utils.checkPermission(getContext(), USE_BIOMETRIC_INTERNAL);
final ServiceProvider provider = getProviderForSensor(sensorId);
@@ -948,11 +949,11 @@
Slog.w(TAG, "No matching provider for onFingerUp, sensorId: " + sensorId);
return;
}
- provider.onPointerUp(sensorId);
+ provider.onPointerUp(requestId, sensorId);
}
@Override
- public void onUiReady(int sensorId) {
+ public void onUiReady(long requestId, int sensorId) {
Utils.checkPermission(getContext(), USE_BIOMETRIC_INTERNAL);
final ServiceProvider provider = getProviderForSensor(sensorId);
@@ -960,7 +961,7 @@
Slog.w(TAG, "No matching provider for onUiReady, sensorId: " + sensorId);
return;
}
- provider.onUiReady(sensorId);
+ provider.onUiReady(requestId, sensorId);
}
@Override
diff --git a/services/core/java/com/android/server/biometrics/sensors/fingerprint/ServiceProvider.java b/services/core/java/com/android/server/biometrics/sensors/fingerprint/ServiceProvider.java
index 0bdc4eb..9cdbdc9 100644
--- a/services/core/java/com/android/server/biometrics/sensors/fingerprint/ServiceProvider.java
+++ b/services/core/java/com/android/server/biometrics/sensors/fingerprint/ServiceProvider.java
@@ -142,11 +142,11 @@
long getAuthenticatorId(int sensorId, int userId);
- void onPointerDown(int sensorId, int x, int y, float minor, float major);
+ void onPointerDown(long requestId, int sensorId, int x, int y, float minor, float major);
- void onPointerUp(int sensorId);
+ void onPointerUp(long requestId, int sensorId);
- void onUiReady(int sensorId);
+ void onUiReady(long requestId, int sensorId);
void setUdfpsOverlayController(@NonNull IUdfpsOverlayController controller);
diff --git a/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintProvider.java b/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintProvider.java
index f810bca..1fac8a8 100644
--- a/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintProvider.java
+++ b/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintProvider.java
@@ -580,39 +580,37 @@
}
@Override
- public void onPointerDown(int sensorId, int x, int y, float minor, float major) {
+ public void onPointerDown(long requestId, int sensorId, int x, int y,
+ float minor, float major) {
final BaseClientMonitor client =
- mSensors.get(sensorId).getScheduler().getCurrentClient();
+ mSensors.get(sensorId).getScheduler().getCurrentClientIfMatches(requestId);
if (!(client instanceof Udfps)) {
Slog.e(getTag(), "onPointerDown received during client: " + client);
return;
}
- final Udfps udfps = (Udfps) client;
- udfps.onPointerDown(x, y, minor, major);
+ ((Udfps) client).onPointerDown(x, y, minor, major);
}
@Override
- public void onPointerUp(int sensorId) {
+ public void onPointerUp(long requestId, int sensorId) {
final BaseClientMonitor client =
- mSensors.get(sensorId).getScheduler().getCurrentClient();
+ mSensors.get(sensorId).getScheduler().getCurrentClientIfMatches(requestId);
if (!(client instanceof Udfps)) {
Slog.e(getTag(), "onPointerUp received during client: " + client);
return;
}
- final Udfps udfps = (Udfps) client;
- udfps.onPointerUp();
+ ((Udfps) client).onPointerUp();
}
@Override
- public void onUiReady(int sensorId) {
+ public void onUiReady(long requestId, int sensorId) {
final BaseClientMonitor client =
- mSensors.get(sensorId).getScheduler().getCurrentClient();
+ mSensors.get(sensorId).getScheduler().getCurrentClientIfMatches(requestId);
if (!(client instanceof Udfps)) {
Slog.e(getTag(), "onUiReady received during client: " + client);
return;
}
- final Udfps udfps = (Udfps) client;
- udfps.onUiReady();
+ ((Udfps) client).onUiReady();
}
@Override
diff --git a/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/Fingerprint21.java b/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/Fingerprint21.java
index 9d60859..1d2a365 100644
--- a/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/Fingerprint21.java
+++ b/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/Fingerprint21.java
@@ -792,36 +792,34 @@
}
@Override
- public void onPointerDown(int sensorId, int x, int y, float minor, float major) {
- final BaseClientMonitor client = mScheduler.getCurrentClient();
+ public void onPointerDown(long requestId, int sensorId, int x, int y,
+ float minor, float major) {
+ final BaseClientMonitor client = mScheduler.getCurrentClientIfMatches(requestId);
if (!(client instanceof Udfps)) {
Slog.w(TAG, "onFingerDown received during client: " + client);
return;
}
- final Udfps udfps = (Udfps) client;
- udfps.onPointerDown(x, y, minor, major);
+ ((Udfps) client).onPointerDown(x, y, minor, major);
}
@Override
- public void onPointerUp(int sensorId) {
- final BaseClientMonitor client = mScheduler.getCurrentClient();
+ public void onPointerUp(long requestId, int sensorId) {
+ final BaseClientMonitor client = mScheduler.getCurrentClientIfMatches(requestId);
if (!(client instanceof Udfps)) {
Slog.w(TAG, "onFingerDown received during client: " + client);
return;
}
- final Udfps udfps = (Udfps) client;
- udfps.onPointerUp();
+ ((Udfps) client).onPointerUp();
}
@Override
- public void onUiReady(int sensorId) {
- final BaseClientMonitor client = mScheduler.getCurrentClient();
+ public void onUiReady(long requestId, int sensorId) {
+ final BaseClientMonitor client = mScheduler.getCurrentClientIfMatches(requestId);
if (!(client instanceof Udfps)) {
Slog.w(TAG, "onUiReady received during client: " + client);
return;
}
- final Udfps udfps = (Udfps) client;
- udfps.onUiReady();
+ ((Udfps) client).onUiReady();
}
@Override
diff --git a/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/Fingerprint21UdfpsMock.java b/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/Fingerprint21UdfpsMock.java
index 149526f..a4e343e 100644
--- a/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/Fingerprint21UdfpsMock.java
+++ b/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/Fingerprint21UdfpsMock.java
@@ -441,7 +441,8 @@
}
@Override
- public void onPointerDown(int sensorId, int x, int y, float minor, float major) {
+ public void onPointerDown(long requestId, int sensorId, int x, int y, float minor,
+ float major) {
mHandler.post(() -> {
Slog.d(TAG, "onFingerDown");
final AuthenticationConsumer lastAuthenticatedConsumer =
@@ -488,7 +489,7 @@
}
@Override
- public void onPointerUp(int sensorId) {
+ public void onPointerUp(long requestId, int sensorId) {
mHandler.post(() -> {
Slog.d(TAG, "onFingerUp");
diff --git a/services/core/java/com/android/server/connectivity/Vpn.java b/services/core/java/com/android/server/connectivity/Vpn.java
index c0df095..a6da4a6 100644
--- a/services/core/java/com/android/server/connectivity/Vpn.java
+++ b/services/core/java/com/android/server/connectivity/Vpn.java
@@ -75,6 +75,7 @@
import android.net.UidRangeParcel;
import android.net.UnderlyingNetworkInfo;
import android.net.VpnManager;
+import android.net.VpnProfileState;
import android.net.VpnService;
import android.net.VpnTransportInfo;
import android.net.ipsec.ike.ChildSessionCallback;
@@ -3438,6 +3439,45 @@
}
}
+ private @VpnProfileState.State int getStateFromLegacyState(int legacyState) {
+ switch (legacyState) {
+ case LegacyVpnInfo.STATE_CONNECTING:
+ return VpnProfileState.STATE_CONNECTING;
+ case LegacyVpnInfo.STATE_CONNECTED:
+ return VpnProfileState.STATE_CONNECTED;
+ case LegacyVpnInfo.STATE_DISCONNECTED:
+ return VpnProfileState.STATE_DISCONNECTED;
+ case LegacyVpnInfo.STATE_FAILED:
+ return VpnProfileState.STATE_FAILED;
+ default:
+ Log.wtf(TAG, "Unhandled state " + legacyState
+ + ", treat it as STATE_DISCONNECTED");
+ return VpnProfileState.STATE_DISCONNECTED;
+ }
+ }
+
+ private VpnProfileState makeVpnProfileState() {
+ // TODO: mSessionKey will be moved to Ikev2VpnRunner once aosp/2007077 is merged, so after
+ // merging aosp/2007077, here should check Ikev2VpnRunner is null or not. Session key will
+ // be null if Ikev2VpnRunner is null.
+ return new VpnProfileState(getStateFromLegacyState(mLegacyState), mSessionKey, mAlwaysOn,
+ mLockdown);
+ }
+
+ /**
+ * Retrieve the VpnProfileState for the profile provisioned by the given package.
+ *
+ * @return the VpnProfileState with current information, or null if there was no profile
+ * provisioned by the given package.
+ */
+ @Nullable
+ public synchronized VpnProfileState getProvisionedVpnProfileState(
+ @NonNull String packageName) {
+ requireNonNull(packageName, "No package name provided");
+ enforceNotRestrictedUser();
+ return isCurrentIkev2VpnLocked(packageName) ? makeVpnProfileState() : null;
+ }
+
/**
* Proxy to allow testing
*
diff --git a/services/core/java/com/android/server/content/ContentService.java b/services/core/java/com/android/server/content/ContentService.java
index fadcce9..954b930 100644
--- a/services/core/java/com/android/server/content/ContentService.java
+++ b/services/core/java/com/android/server/content/ContentService.java
@@ -20,6 +20,7 @@
import android.Manifest;
import android.accounts.Account;
+import android.accounts.AccountManagerInternal;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.RequiresPermission;
@@ -28,7 +29,10 @@
import android.app.ActivityManagerInternal;
import android.app.AppGlobals;
import android.app.AppOpsManager;
+import android.app.compat.CompatChanges;
import android.app.job.JobInfo;
+import android.compat.annotation.ChangeId;
+import android.compat.annotation.EnabledAfter;
import android.content.BroadcastReceiver;
import android.content.ComponentName;
import android.content.ContentResolver;
@@ -106,6 +110,13 @@
*/
private static final long BACKGROUND_OBSERVER_DELAY = 10 * DateUtils.SECOND_IN_MILLIS;
+ /**
+ * Enables checking for account access for the calling uid on all sync-related APIs.
+ */
+ @ChangeId
+ @EnabledAfter(targetSdkVersion = android.os.Build.VERSION_CODES.S_V2)
+ public static final long ACCOUNT_ACCESS_CHECK_CHANGE_ID = 201794303L;
+
public static class Lifecycle extends SystemService {
private ContentService mService;
@@ -157,6 +168,8 @@
private SyncManager mSyncManager = null;
private final Object mSyncManagerLock = new Object();
+ private final AccountManagerInternal mAccountManagerInternal;
+
private static final BinderDeathDispatcher<IContentObserver> sObserverDeathDispatcher =
new BinderDeathDispatcher<>();
@@ -317,6 +330,8 @@
localeFilter.addAction(Intent.ACTION_LOCALE_CHANGED);
mContext.registerReceiverAsUser(mCacheReceiver, UserHandle.ALL,
localeFilter, null, null);
+
+ mAccountManagerInternal = LocalServices.getService(AccountManagerInternal.class);
}
void onBootPhase(int phase) {
@@ -593,6 +608,10 @@
final int callingUid = Binder.getCallingUid();
final int callingPid = Binder.getCallingPid();
+ if (!hasAccountAccess(true, account, callingUid)) {
+ return;
+ }
+
validateExtras(callingUid, extras);
final int syncExemption = getSyncExemptionAndCleanUpExtrasForCaller(callingUid, extras);
@@ -642,11 +661,14 @@
@Override
public void syncAsUser(SyncRequest request, int userId, String callingPackage) {
enforceCrossUserPermission(userId, "no permission to request sync as user: " + userId);
+
final int callingUid = Binder.getCallingUid();
final int callingPid = Binder.getCallingPid();
+ if (!hasAccountAccess(true, request.getAccount(), callingUid)) {
+ return;
+ }
final Bundle extras = request.getBundle();
-
validateExtras(callingUid, extras);
final int syncExemption = getSyncExemptionAndCleanUpExtrasForCaller(callingUid, extras);
@@ -853,6 +875,9 @@
"no permission to read the sync settings for user " + userId);
mContext.enforceCallingOrSelfPermission(Manifest.permission.READ_SYNC_SETTINGS,
"no permission to read the sync settings");
+ if (!hasAccountAccess(true, account, Binder.getCallingUid())) {
+ return false;
+ }
final long identityToken = clearCallingIdentity();
try {
@@ -882,8 +907,13 @@
"no permission to write the sync settings");
enforceCrossUserPermission(userId,
"no permission to modify the sync settings for user " + userId);
+
final int callingUid = Binder.getCallingUid();
final int callingPid = Binder.getCallingPid();
+ if (!hasAccountAccess(true, account, callingUid)) {
+ return;
+ }
+
final int syncExemptionFlag = getSyncExemptionForCaller(callingUid);
final long identityToken = clearCallingIdentity();
@@ -912,7 +942,11 @@
mContext.enforceCallingOrSelfPermission(Manifest.permission.WRITE_SYNC_SETTINGS,
"no permission to write the sync settings");
- validateExtras(Binder.getCallingUid(), extras);
+ final int callingUid = Binder.getCallingUid();
+ if (!hasAccountAccess(true, account, callingUid)) {
+ return;
+ }
+ validateExtras(callingUid, extras);
int userId = UserHandle.getCallingUserId();
@@ -942,9 +976,11 @@
mContext.enforceCallingOrSelfPermission(Manifest.permission.WRITE_SYNC_SETTINGS,
"no permission to write the sync settings");
- validateExtras(Binder.getCallingUid(), extras);
-
final int callingUid = Binder.getCallingUid();
+ if (!hasAccountAccess(true, account, callingUid)) {
+ return;
+ }
+ validateExtras(callingUid, extras);
int userId = UserHandle.getCallingUserId();
final long identityToken = clearCallingIdentity();
@@ -969,6 +1005,9 @@
}
mContext.enforceCallingOrSelfPermission(Manifest.permission.READ_SYNC_SETTINGS,
"no permission to read the sync settings");
+ if (!hasAccountAccess(true, account, Binder.getCallingUid())) {
+ return new ArrayList<>(); // return a new empty list for consistent behavior
+ }
int userId = UserHandle.getCallingUserId();
final long identityToken = clearCallingIdentity();
@@ -995,6 +1034,9 @@
"no permission to read the sync settings for user " + userId);
mContext.enforceCallingOrSelfPermission(Manifest.permission.READ_SYNC_SETTINGS,
"no permission to read the sync settings");
+ if (!hasAccountAccess(true, account, Binder.getCallingUid())) {
+ return SyncStorageEngine.AuthorityInfo.NOT_SYNCABLE; // to keep behavior consistent
+ }
final long identityToken = clearCallingIdentity();
try {
@@ -1031,6 +1073,9 @@
syncable = normalizeSyncable(syncable);
final int callingUid = Binder.getCallingUid();
final int callingPid = Binder.getCallingPid();
+ if (!hasAccountAccess(true, account, callingUid)) {
+ return;
+ }
final long identityToken = clearCallingIdentity();
try {
@@ -1103,6 +1148,10 @@
public boolean isSyncActive(Account account, String authority, ComponentName cname) {
mContext.enforceCallingOrSelfPermission(Manifest.permission.READ_SYNC_STATS,
"no permission to read the sync stats");
+ if (!hasAccountAccess(true, account, Binder.getCallingUid())) {
+ return false;
+ }
+
int userId = UserHandle.getCallingUserId();
final long identityToken = clearCallingIdentity();
try {
@@ -1165,6 +1214,9 @@
"no permission to read the sync stats for user " + userId);
mContext.enforceCallingOrSelfPermission(Manifest.permission.READ_SYNC_STATS,
"no permission to read the sync stats");
+ if (!hasAccountAccess(true, account, Binder.getCallingUid())) {
+ return null;
+ }
final long identityToken = clearCallingIdentity();
try {
@@ -1196,6 +1248,10 @@
"no permission to read the sync stats");
enforceCrossUserPermission(userId,
"no permission to retrieve the sync settings for user " + userId);
+ if (!hasAccountAccess(true, account, Binder.getCallingUid())) {
+ return false;
+ }
+
final long identityToken = clearCallingIdentity();
SyncManager syncManager = getSyncManager();
if (syncManager == null) return false;
@@ -1405,6 +1461,32 @@
Manifest.permission.INTERACT_ACROSS_USERS_FULL, message);
}
+ /**
+ * Checks to see if the given account is accessible by the provided uid.
+ *
+ * @param checkCompatFlag whether to check if the ACCOUNT_ACCESS_CHECK_CHANGE_ID flag is enabled
+ * @param account the account trying to be accessed
+ * @param uid the uid trying to access the account
+ * @return {@code true} if the account is accessible by the given uid, {@code false} otherwise
+ */
+ private boolean hasAccountAccess(boolean checkCompatFlag, Account account, int uid) {
+ if (account == null) {
+ // If the account is null, it means to check for all accounts hence skip the check here.
+ return true;
+ }
+ if (checkCompatFlag
+ && !CompatChanges.isChangeEnabled(ACCOUNT_ACCESS_CHECK_CHANGE_ID, uid)) {
+ return true;
+ }
+
+ final long identityToken = clearCallingIdentity();
+ try {
+ return mAccountManagerInternal.hasAccountAccess(account, uid);
+ } finally {
+ restoreCallingIdentity(identityToken);
+ }
+ }
+
private static int normalizeSyncable(int syncable) {
if (syncable > 0) {
return SyncStorageEngine.AuthorityInfo.SYNCABLE;
diff --git a/services/core/java/com/android/server/display/ColorFade.java b/services/core/java/com/android/server/display/ColorFade.java
index 7cb2921..cb04ddf 100644
--- a/services/core/java/com/android/server/display/ColorFade.java
+++ b/services/core/java/com/android/server/display/ColorFade.java
@@ -156,9 +156,15 @@
mMode = mode;
+ DisplayInfo displayInfo = mDisplayManagerInternal.getDisplayInfo(mDisplayId);
+ if (displayInfo == null) {
+ // displayInfo can be null if the associated display has been removed. There
+ // is a delay between the display being removed and ColorFade being dismissed.
+ return false;
+ }
+
// Get the display size and layer stack.
// This is not expected to change while the color fade surface is showing.
- DisplayInfo displayInfo = mDisplayManagerInternal.getDisplayInfo(mDisplayId);
mDisplayLayerStack = displayInfo.layerStack;
mDisplayWidth = displayInfo.getNaturalWidth();
mDisplayHeight = displayInfo.getNaturalHeight();
diff --git a/services/core/java/com/android/server/display/LocalDisplayAdapter.java b/services/core/java/com/android/server/display/LocalDisplayAdapter.java
index 7a0cf4b..540ae81 100644
--- a/services/core/java/com/android/server/display/LocalDisplayAdapter.java
+++ b/services/core/java/com/android/server/display/LocalDisplayAdapter.java
@@ -73,6 +73,8 @@
private final SurfaceControlProxy mSurfaceControlProxy;
+ private final boolean mIsBootDisplayModeSupported;
+
// Called with SyncRoot lock held.
public LocalDisplayAdapter(DisplayManagerService.SyncRoot syncRoot,
Context context, Handler handler, Listener listener) {
@@ -85,6 +87,7 @@
super(syncRoot, context, handler, listener, TAG);
mInjector = injector;
mSurfaceControlProxy = mInjector.getSurfaceControlProxy();
+ mIsBootDisplayModeSupported = mSurfaceControlProxy.getBootDisplayModeSupport();
}
@Override
@@ -349,8 +352,7 @@
if (preferredRecord != null) {
int preferredModeId = preferredRecord.mMode.getModeId();
- if (mSurfaceControlProxy.getBootDisplayModeSupport()
- && mSystemPreferredModeId != preferredModeId) {
+ if (mIsBootDisplayModeSupported && mSystemPreferredModeId != preferredModeId) {
mSystemPreferredModeId = preferredModeId;
preferredModeChanged = true;
}
@@ -900,7 +902,7 @@
}
updateDeviceInfoLocked();
- if (!mSurfaceControlProxy.getBootDisplayModeSupport()) {
+ if (!mIsBootDisplayModeSupported) {
return;
}
if (mUserPreferredModeId == INVALID_MODE_ID) {
diff --git a/services/core/java/com/android/server/dreams/DreamManagerService.java b/services/core/java/com/android/server/dreams/DreamManagerService.java
index 22d32a6..50f5536 100644
--- a/services/core/java/com/android/server/dreams/DreamManagerService.java
+++ b/services/core/java/com/android/server/dreams/DreamManagerService.java
@@ -467,7 +467,9 @@
}
mCurrentDreamDozeScreenState = Display.STATE_UNKNOWN;
mCurrentDreamDozeScreenBrightness = PowerManager.BRIGHTNESS_DEFAULT;
- mAtmInternal.notifyDreamStateChanged(false);
+ mHandler.post(() -> {
+ mAtmInternal.notifyDreamStateChanged(false);
+ });
}
private void checkPermission(String permission) {
diff --git a/services/core/java/com/android/server/locales/LocaleManagerService.java b/services/core/java/com/android/server/locales/LocaleManagerService.java
index 176c08c..924db6a 100644
--- a/services/core/java/com/android/server/locales/LocaleManagerService.java
+++ b/services/core/java/com/android/server/locales/LocaleManagerService.java
@@ -22,12 +22,14 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.UserIdInt;
+import android.app.ActivityManager;
import android.app.ActivityManagerInternal;
import android.app.ILocaleManager;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.content.pm.PackageManagerInternal;
+import android.content.res.Configuration;
import android.os.Binder;
import android.os.HandlerThread;
import android.os.LocaleList;
@@ -154,6 +156,12 @@
}
@Override
+ @NonNull
+ public LocaleList getSystemLocales() throws RemoteException {
+ return LocaleManagerService.this.getSystemLocales();
+ }
+
+ @Override
public void onShellCommand(FileDescriptor in, FileDescriptor out,
FileDescriptor err, String[] args, ShellCallback callback,
ResultReceiver resultReceiver) {
@@ -426,6 +434,32 @@
return null;
}
+ /**
+ * Returns the current system locales.
+ */
+ @NonNull
+ public LocaleList getSystemLocales() throws RemoteException {
+ final long token = Binder.clearCallingIdentity();
+ try {
+ return getSystemLocalesUnchecked();
+ } finally {
+ Binder.restoreCallingIdentity(token);
+ }
+ }
+
+ @NonNull
+ private LocaleList getSystemLocalesUnchecked() throws RemoteException {
+ LocaleList systemLocales = null;
+ Configuration conf = ActivityManager.getService().getConfiguration();
+ if (conf != null) {
+ systemLocales = conf.getLocales();
+ }
+ if (systemLocales == null) {
+ systemLocales = LocaleList.getEmptyLocaleList();
+ }
+ return systemLocales;
+ }
+
private void logMetric(@NonNull AppLocaleChangedAtomRecord atomRecordForMetrics) {
FrameworkStatsLog.write(FrameworkStatsLog.APPLICATION_LOCALES_CHANGED,
atomRecordForMetrics.mCallingUid,
diff --git a/services/core/java/com/android/server/locales/TEST_MAPPING b/services/core/java/com/android/server/locales/TEST_MAPPING
index 27d2851..160542b 100644
--- a/services/core/java/com/android/server/locales/TEST_MAPPING
+++ b/services/core/java/com/android/server/locales/TEST_MAPPING
@@ -9,10 +9,13 @@
]
},
{
- "name": "CtsLocaleManagerTestCases"
- },
- {
"name": "CtsLocaleManagerHostTestCases"
}
+ ],
+ "postsubmit": [
+ // TODO(b/225192026): Move back to presubmit after b/225192026 is fixed
+ {
+ "name": "CtsLocaleManagerTestCases"
+ }
]
}
diff --git a/services/core/java/com/android/server/location/LocationPermissions.java b/services/core/java/com/android/server/location/LocationPermissions.java
index be702d9..ca2ff60 100644
--- a/services/core/java/com/android/server/location/LocationPermissions.java
+++ b/services/core/java/com/android/server/location/LocationPermissions.java
@@ -19,7 +19,6 @@
import static android.Manifest.permission.ACCESS_COARSE_LOCATION;
import static android.Manifest.permission.ACCESS_FINE_LOCATION;
import static android.Manifest.permission.LOCATION_BYPASS;
-import static android.Manifest.permission.WRITE_SECURE_SETTINGS;
import static android.content.pm.PackageManager.PERMISSION_GRANTED;
import android.annotation.IntDef;
@@ -134,15 +133,11 @@
* perissions.
*/
public static void enforceBypassPermission(Context context, int uid, int pid) {
- if (context.checkPermission(WRITE_SECURE_SETTINGS, pid, uid) == PERMISSION_GRANTED) {
- // TODO: disallow WRITE_SECURE_SETTINGS permission.
- return;
- }
if (context.checkPermission(LOCATION_BYPASS, pid, uid) == PERMISSION_GRANTED) {
return;
}
throw new SecurityException("uid" + uid + " does not have " + LOCATION_BYPASS
- + "or " + WRITE_SECURE_SETTINGS + ".");
+ + ".");
}
/**
diff --git a/services/core/java/com/android/server/locksettings/LockSettingsService.java b/services/core/java/com/android/server/locksettings/LockSettingsService.java
index 52834cb..135af2d 100644
--- a/services/core/java/com/android/server/locksettings/LockSettingsService.java
+++ b/services/core/java/com/android/server/locksettings/LockSettingsService.java
@@ -252,8 +252,6 @@
private final RebootEscrowManager mRebootEscrowManager;
- private boolean mFirstCallToVold;
-
// Current password metric for all users on the device. Updated when user unlocks
// the device or changes password. Removed when user is stopped.
@GuardedBy("this")
@@ -597,8 +595,6 @@
mStrongAuth = injector.getStrongAuth();
mActivityManager = injector.getActivityManager();
- mFirstCallToVold = true;
-
IntentFilter filter = new IntentFilter();
filter.addAction(Intent.ACTION_USER_ADDED);
filter.addAction(Intent.ACTION_USER_STARTING);
@@ -689,19 +685,19 @@
}
private String getEncryptionNotificationTitle() {
- return mInjector.getDevicePolicyManager().getString(
+ return mInjector.getDevicePolicyManager().getResources().getString(
PROFILE_ENCRYPTED_TITLE,
() -> mContext.getString(R.string.profile_encrypted_title));
}
private String getEncryptionNotificationDetail() {
- return mInjector.getDevicePolicyManager().getString(
+ return mInjector.getDevicePolicyManager().getResources().getString(
PROFILE_ENCRYPTED_DETAIL,
() -> mContext.getString(R.string.profile_encrypted_detail));
}
private String getEncryptionNotificationMessage() {
- return mInjector.getDevicePolicyManager().getString(
+ return mInjector.getDevicePolicyManager().getResources().getString(
PROFILE_ENCRYPTED_MESSAGE,
() -> mContext.getString(R.string.profile_encrypted_message));
}
@@ -2474,77 +2470,6 @@
});
}
- private LockscreenCredential createPattern(String patternString) {
- final byte[] patternBytes = patternString.getBytes();
- LockscreenCredential pattern = LockscreenCredential.createPattern(
- LockPatternUtils.byteArrayToPattern(patternBytes));
- Arrays.fill(patternBytes, (byte) 0);
- return pattern;
- }
-
- @Override
- public boolean checkVoldPassword(int userId) {
- if (!mFirstCallToVold) {
- return false;
- }
- mFirstCallToVold = false;
-
- checkPasswordReadPermission();
-
- // There's no guarantee that this will safely connect, but if it fails
- // we will simply show the lock screen when we shouldn't, so relatively
- // benign. There is an outside chance something nasty would happen if
- // this service restarted before vold stales out the password in this
- // case. The nastiness is limited to not showing the lock screen when
- // we should, within the first minute of decrypting the phone if this
- // service can't connect to vold, it restarts, and then the new instance
- // does successfully connect.
- final IStorageManager service = mInjector.getStorageManager();
- // TODO(b/120484642): Update vold to return a password as a byte array
- String password;
- final long identity = Binder.clearCallingIdentity();
- try {
- password = service.getPassword();
- service.clearPassword();
- } catch (RemoteException e) {
- Slog.w(TAG, "vold getPassword() failed", e);
- return false;
- } finally {
- Binder.restoreCallingIdentity(identity);
- }
- if (TextUtils.isEmpty(password)) {
- return false;
- }
-
- try {
- final LockscreenCredential credential;
- switch (getCredentialTypeInternal(userId)) {
- case CREDENTIAL_TYPE_PATTERN:
- credential = createPattern(password);
- break;
- case CREDENTIAL_TYPE_PIN:
- credential = LockscreenCredential.createPin(password);
- break;
- case CREDENTIAL_TYPE_PASSWORD:
- credential = LockscreenCredential.createPassword(password);
- break;
- default:
- credential = null;
- Slog.e(TAG, "Unknown credential type");
- }
-
- if (credential != null
- && checkCredential(credential, userId, null /* progressCallback */)
- .getResponseCode() == GateKeeperResponse.RESPONSE_OK) {
- return true;
- }
- } catch (Exception e) {
- Slog.e(TAG, "checkVoldPassword failed: ", e);
- }
-
- return false;
- }
-
private void removeUser(int userId, boolean unknownUser) {
Slog.i(TAG, "RemoveUser: " + userId);
removeBiometricsForUser(userId);
diff --git a/services/core/java/com/android/server/media/projection/MediaProjectionManagerService.java b/services/core/java/com/android/server/media/projection/MediaProjectionManagerService.java
index 3ce8e46..1937852 100644
--- a/services/core/java/com/android/server/media/projection/MediaProjectionManagerService.java
+++ b/services/core/java/com/android/server/media/projection/MediaProjectionManagerService.java
@@ -45,6 +45,7 @@
import android.os.UserHandle;
import android.util.ArrayMap;
import android.util.Slog;
+import android.window.WindowContainerToken;
import com.android.internal.util.ArrayUtils;
import com.android.internal.util.DumpUtils;
@@ -410,6 +411,7 @@
private IBinder mToken;
private IBinder.DeathRecipient mDeathEater;
private boolean mRestoreSystemAlertWindow;
+ private WindowContainerToken mTaskRecordingWindowContainerToken = null;
MediaProjection(int type, int uid, String packageName, int targetSdkVersion,
boolean isPrivileged) {
@@ -568,7 +570,7 @@
}
}
- @Override
+ @Override // Binder call
public void registerCallback(IMediaProjectionCallback callback) {
if (callback == null) {
throw new IllegalArgumentException("callback must not be null");
@@ -576,7 +578,7 @@
mCallbackDelegate.add(callback);
}
- @Override
+ @Override // Binder call
public void unregisterCallback(IMediaProjectionCallback callback) {
if (callback == null) {
throw new IllegalArgumentException("callback must not be null");
@@ -584,6 +586,17 @@
mCallbackDelegate.remove(callback);
}
+ @Override // Binder call
+ public void setTaskRecordingWindowContainerToken(WindowContainerToken token) {
+ // TODO(b/221417940) set the task id to record from sysui, for the package chosen.
+ mTaskRecordingWindowContainerToken = token;
+ }
+
+ @Override // Binder call
+ public WindowContainerToken getTaskRecordingWindowContainerToken() {
+ return mTaskRecordingWindowContainerToken;
+ }
+
public MediaProjectionInfo getProjectionInfo() {
return new MediaProjectionInfo(packageName, userHandle);
}
diff --git a/services/core/java/com/android/server/net/NetworkPolicyManagerService.java b/services/core/java/com/android/server/net/NetworkPolicyManagerService.java
index 9f573c2..57ffba7 100644
--- a/services/core/java/com/android/server/net/NetworkPolicyManagerService.java
+++ b/services/core/java/com/android/server/net/NetworkPolicyManagerService.java
@@ -4094,7 +4094,7 @@
"updateNetworkStats: " + uid + "/" + (uidForeground ? "F" : "B"));
}
try {
- mNetworkStats.setUidForeground(uid, uidForeground);
+ mNetworkStats.noteUidForeground(uid, uidForeground);
} finally {
Trace.traceEnd(Trace.TRACE_TAG_NETWORK);
}
@@ -5421,6 +5421,11 @@
try {
mNetworkManager.setUidOnMeteredNetworkDenylist(uid, enable);
mLogger.meteredAllowlistChanged(uid, enable);
+ if (Process.isApplicationUid(uid)) {
+ final int sdkSandboxUid = Process.toSdkSandboxUid(uid);
+ mNetworkManager.setUidOnMeteredNetworkDenylist(sdkSandboxUid, enable);
+ mLogger.meteredAllowlistChanged(sdkSandboxUid, enable);
+ }
} catch (IllegalStateException e) {
Log.wtf(TAG, "problem setting denylist (" + enable + ") rules for " + uid, e);
} catch (RemoteException e) {
@@ -5433,6 +5438,11 @@
try {
mNetworkManager.setUidOnMeteredNetworkAllowlist(uid, enable);
mLogger.meteredDenylistChanged(uid, enable);
+ if (Process.isApplicationUid(uid)) {
+ final int sdkSandboxUid = Process.toSdkSandboxUid(uid);
+ mNetworkManager.setUidOnMeteredNetworkAllowlist(sdkSandboxUid, enable);
+ mLogger.meteredDenylistChanged(sdkSandboxUid, enable);
+ }
} catch (IllegalStateException e) {
Log.wtf(TAG, "problem setting allowlist (" + enable + ") rules for " + uid, e);
} catch (RemoteException e) {
@@ -5471,12 +5481,31 @@
}
}
+ private void addSdkSandboxUidsIfNeeded(SparseIntArray uidRules) {
+ final int size = uidRules.size();
+ final SparseIntArray sdkSandboxUids = new SparseIntArray();
+ for (int index = 0; index < size; index++) {
+ final int uid = uidRules.keyAt(index);
+ final int rule = uidRules.valueAt(index);
+ if (Process.isApplicationUid(uid)) {
+ sdkSandboxUids.put(Process.toSdkSandboxUid(uid), rule);
+ }
+ }
+
+ for (int index = 0; index < sdkSandboxUids.size(); index++) {
+ final int uid = sdkSandboxUids.keyAt(index);
+ final int rule = sdkSandboxUids.valueAt(index);
+ uidRules.put(uid, rule);
+ }
+ }
+
/**
* Set uid rules on a particular firewall chain. This is going to synchronize the rules given
* here to netd. It will clean up dead rules and make sure the target chain only contains rules
* specified here.
*/
private void setUidFirewallRulesUL(int chain, SparseIntArray uidRules) {
+ addSdkSandboxUidsIfNeeded(uidRules);
try {
int size = uidRules.size();
int[] uids = new int[size];
@@ -5519,6 +5548,11 @@
try {
mNetworkManager.setFirewallUidRule(chain, uid, rule);
mLogger.uidFirewallRuleChanged(chain, uid, rule);
+ if (Process.isApplicationUid(uid)) {
+ final int sdkSandboxUid = Process.toSdkSandboxUid(uid);
+ mNetworkManager.setFirewallUidRule(chain, sdkSandboxUid, rule);
+ mLogger.uidFirewallRuleChanged(chain, sdkSandboxUid, rule);
+ }
} catch (IllegalStateException e) {
Log.wtf(TAG, "problem setting firewall uid rules", e);
} catch (RemoteException e) {
@@ -5555,15 +5589,16 @@
*/
private void resetUidFirewallRules(int uid) {
try {
- mNetworkManager.setFirewallUidRule(FIREWALL_CHAIN_DOZABLE, uid, FIREWALL_RULE_DEFAULT);
- mNetworkManager.setFirewallUidRule(FIREWALL_CHAIN_STANDBY, uid, FIREWALL_RULE_DEFAULT);
- mNetworkManager
- .setFirewallUidRule(FIREWALL_CHAIN_POWERSAVE, uid, FIREWALL_RULE_DEFAULT);
- mNetworkManager
- .setFirewallUidRule(FIREWALL_CHAIN_RESTRICTED, uid, FIREWALL_RULE_DEFAULT);
- mNetworkManager
- .setFirewallUidRule(FIREWALL_CHAIN_LOW_POWER_STANDBY, uid,
- FIREWALL_RULE_DEFAULT);
+ mNetworkManager.setFirewallUidRule(FIREWALL_CHAIN_DOZABLE, uid,
+ FIREWALL_RULE_DEFAULT);
+ mNetworkManager.setFirewallUidRule(FIREWALL_CHAIN_STANDBY, uid,
+ FIREWALL_RULE_DEFAULT);
+ mNetworkManager.setFirewallUidRule(FIREWALL_CHAIN_POWERSAVE, uid,
+ FIREWALL_RULE_DEFAULT);
+ mNetworkManager.setFirewallUidRule(FIREWALL_CHAIN_RESTRICTED, uid,
+ FIREWALL_RULE_DEFAULT);
+ mNetworkManager.setFirewallUidRule(FIREWALL_CHAIN_LOW_POWER_STANDBY, uid,
+ FIREWALL_RULE_DEFAULT);
mNetworkManager.setUidOnMeteredNetworkAllowlist(uid, false);
mLogger.meteredAllowlistChanged(uid, false);
mNetworkManager.setUidOnMeteredNetworkDenylist(uid, false);
@@ -5573,6 +5608,9 @@
} catch (RemoteException e) {
// ignored; service lives in system_server
}
+ if (Process.isApplicationUid(uid)) {
+ resetUidFirewallRules(Process.toSdkSandboxUid(uid));
+ }
}
@Deprecated
diff --git a/services/core/java/com/android/server/notification/ZenModeHelper.java b/services/core/java/com/android/server/notification/ZenModeHelper.java
index 93f1b47..9e0c975 100644
--- a/services/core/java/com/android/server/notification/ZenModeHelper.java
+++ b/services/core/java/com/android/server/notification/ZenModeHelper.java
@@ -104,6 +104,7 @@
// The amount of time rules instances can exist without their owning app being installed.
private static final int RULE_INSTANCE_GRACE_PERIOD = 1000 * 60 * 60 * 72;
+ static final int RULE_LIMIT_PER_PACKAGE = 100;
// pkg|userId => uid
protected final ArrayMap<String, Integer> mRulesUidCache = new ArrayMap<>();
@@ -329,10 +330,10 @@
int newRuleInstanceCount = getCurrentInstanceCount(automaticZenRule.getOwner())
+ getCurrentInstanceCount(automaticZenRule.getConfigurationActivity())
+ 1;
- if (ruleInstanceLimit > 0 && ruleInstanceLimit < newRuleInstanceCount) {
+ if (newRuleInstanceCount > RULE_LIMIT_PER_PACKAGE
+ || (ruleInstanceLimit > 0 && ruleInstanceLimit < newRuleInstanceCount)) {
throw new IllegalArgumentException("Rule instance limit exceeded");
}
-
}
ZenModeConfig newConfig;
diff --git a/services/core/java/com/android/server/pm/AppIdSettingMap.java b/services/core/java/com/android/server/pm/AppIdSettingMap.java
index bbef237..b41a0b8 100644
--- a/services/core/java/com/android/server/pm/AppIdSettingMap.java
+++ b/services/core/java/com/android/server/pm/AppIdSettingMap.java
@@ -17,46 +17,131 @@
package com.android.server.pm;
import android.os.Process;
+import android.util.Log;
+import com.android.server.utils.WatchedArrayList;
import com.android.server.utils.WatchedSparseArray;
+import com.android.server.utils.Watcher;
/**
- * A wrapper over {@link WatchedSparseArray} that tracks the current maximum App ID.
+ * A wrapper over {@link WatchedArrayList} that tracks the current (app ID -> SettingBase) mapping
+ * for non-system apps. Also tracks system app settings in an {@link WatchedSparseArray}.
*/
-public class AppIdSettingMap extends WatchedSparseArray<SettingBase> {
- private int mCurrentMaxAppId;
+final class AppIdSettingMap {
+ /**
+ * We use an ArrayList instead of an SparseArray for non system apps because the number of apps
+ * might be big, and only ArrayList gives us a constant lookup time. For a given app ID, the
+ * index to the corresponding SettingBase object is (appId - FIRST_APPLICATION_ID). If an app ID
+ * doesn't exist (i.e., app is not installed), we fill the corresponding entry with null.
+ */
+ private WatchedArrayList<SettingBase> mNonSystemSettings = new WatchedArrayList<>();
+ private WatchedSparseArray<SettingBase> mSystemSettings = new WatchedSparseArray<>();
+ private int mFirstAvailableAppId = Process.FIRST_APPLICATION_UID;
- @Override
- public void put(int key, SettingBase value) {
- if (key > mCurrentMaxAppId) {
- mCurrentMaxAppId = key;
+ /** Returns true if the requested AppID was valid and not already registered. */
+ public boolean registerExistingAppId(int appId, SettingBase setting, Object name) {
+ if (appId >= Process.FIRST_APPLICATION_UID) {
+ int size = mNonSystemSettings.size();
+ final int index = appId - Process.FIRST_APPLICATION_UID;
+ // fill the array until our index becomes valid
+ while (index >= size) {
+ mNonSystemSettings.add(null);
+ size++;
+ }
+ if (mNonSystemSettings.get(index) != null) {
+ PackageManagerService.reportSettingsProblem(Log.WARN,
+ "Adding duplicate app id: " + appId
+ + " name=" + name);
+ return false;
+ }
+ mNonSystemSettings.set(index, setting);
+ } else {
+ if (mSystemSettings.get(appId) != null) {
+ PackageManagerService.reportSettingsProblem(Log.WARN,
+ "Adding duplicate shared id: " + appId
+ + " name=" + name);
+ return false;
+ }
+ mSystemSettings.put(appId, setting);
}
- super.put(key, value);
+ return true;
}
- @Override
+ public SettingBase getSetting(int appId) {
+ if (appId >= Process.FIRST_APPLICATION_UID) {
+ final int size = mNonSystemSettings.size();
+ final int index = appId - Process.FIRST_APPLICATION_UID;
+ return index < size ? mNonSystemSettings.get(index) : null;
+ } else {
+ return mSystemSettings.get(appId);
+ }
+ }
+
+ public void removeSetting(int appId) {
+ if (appId >= Process.FIRST_APPLICATION_UID) {
+ final int size = mNonSystemSettings.size();
+ final int index = appId - Process.FIRST_APPLICATION_UID;
+ if (index < size) {
+ mNonSystemSettings.set(index, null);
+ }
+ } else {
+ mSystemSettings.remove(appId);
+ }
+ setFirstAvailableAppId(appId + 1);
+ }
+
+ // This should be called (at least) whenever an application is removed
+ private void setFirstAvailableAppId(int uid) {
+ if (uid > mFirstAvailableAppId) {
+ mFirstAvailableAppId = uid;
+ }
+ }
+
+ public void replaceSetting(int appId, SettingBase setting) {
+ if (appId >= Process.FIRST_APPLICATION_UID) {
+ final int size = mNonSystemSettings.size();
+ final int index = appId - Process.FIRST_APPLICATION_UID;
+ if (index < size) {
+ mNonSystemSettings.set(index, setting);
+ } else {
+ PackageManagerService.reportSettingsProblem(Log.WARN,
+ "Error in package manager settings: calling replaceAppIdLpw to"
+ + " replace SettingBase at appId=" + appId
+ + " but nothing is replaced.");
+ }
+ } else {
+ mSystemSettings.put(appId, setting);
+ }
+ }
+
+ /** Returns a new AppID or -1 if we could not find an available AppID to assign */
+ public int acquireAndRegisterNewAppId(SettingBase obj) {
+ final int size = mNonSystemSettings.size();
+ for (int i = mFirstAvailableAppId - Process.FIRST_APPLICATION_UID; i < size; i++) {
+ if (mNonSystemSettings.get(i) == null) {
+ mNonSystemSettings.set(i, obj);
+ return Process.FIRST_APPLICATION_UID + i;
+ }
+ }
+
+ // None left?
+ if (size > (Process.LAST_APPLICATION_UID - Process.FIRST_APPLICATION_UID)) {
+ return -1;
+ }
+
+ mNonSystemSettings.add(obj);
+ return Process.FIRST_APPLICATION_UID + size;
+ }
+
public AppIdSettingMap snapshot() {
AppIdSettingMap l = new AppIdSettingMap();
- snapshot(l, this);
+ mNonSystemSettings.snapshot(l.mNonSystemSettings, mNonSystemSettings);
+ mSystemSettings.snapshot(l.mSystemSettings, mSystemSettings);
return l;
}
- /**
- * @return the maximum of all the App IDs that have been added to the map. 0 if map is empty.
- */
- public int getCurrentMaxAppId() {
- return mCurrentMaxAppId;
- }
-
- /**
- * @return the next available App ID that has not been added to the map
- */
- public int getNextAvailableAppId() {
- if (mCurrentMaxAppId == 0) {
- // No app id has been added yet
- return Process.FIRST_APPLICATION_UID;
- } else {
- return mCurrentMaxAppId + 1;
- }
+ public void registerObserver(Watcher observer) {
+ mNonSystemSettings.registerObserver(observer);
+ mSystemSettings.registerObserver(observer);
}
}
diff --git a/services/core/java/com/android/server/pm/BackgroundDexOptService.java b/services/core/java/com/android/server/pm/BackgroundDexOptService.java
index 9ff4aab..d26a1ac 100644
--- a/services/core/java/com/android/server/pm/BackgroundDexOptService.java
+++ b/services/core/java/com/android/server/pm/BackgroundDexOptService.java
@@ -253,7 +253,8 @@
*
* <p>This is only for shell command and only root or shell user can use this.
*
- * @param packageNames dex optimize the passed packages or all packages if null
+ * @param packageNames dex optimize the passed packages in the given order, or all packages in
+ * the default order if null
*
* @return true if dex optimization is complete. false if the task is cancelled or if there was
* an error.
@@ -268,11 +269,11 @@
resetStatesForNewDexOptRunLocked(Thread.currentThread());
}
PackageManagerService pm = mInjector.getPackageManagerService();
- ArraySet<String> packagesToOptimize;
+ List<String> packagesToOptimize;
if (packageNames == null) {
packagesToOptimize = mDexOptHelper.getOptimizablePackages(pm.snapshotComputer());
} else {
- packagesToOptimize = new ArraySet<>(packageNames);
+ packagesToOptimize = packageNames;
}
return runIdleOptimization(pm, packagesToOptimize, /* isPostBootUpdate= */ false);
} finally {
@@ -335,7 +336,7 @@
return false;
}
- ArraySet<String> pkgs = mDexOptHelper.getOptimizablePackages(pm.snapshotComputer());
+ List<String> pkgs = mDexOptHelper.getOptimizablePackages(pm.snapshotComputer());
if (pkgs.isEmpty()) {
Slog.i(TAG, "No packages to optimize");
markPostBootUpdateCompleted(params);
@@ -525,7 +526,7 @@
}
/** Returns true if completed */
- private boolean runIdleOptimization(PackageManagerService pm, ArraySet<String> pkgs,
+ private boolean runIdleOptimization(PackageManagerService pm, List<String> pkgs,
boolean isPostBootUpdate) {
synchronized (mLock) {
mLastExecutionStartTimeMs = SystemClock.elapsedRealtime();
@@ -581,10 +582,9 @@
}
@Status
- private int idleOptimizePackages(PackageManagerService pm, ArraySet<String> pkgs,
+ private int idleOptimizePackages(PackageManagerService pm, List<String> pkgs,
long lowStorageThreshold, boolean isPostBootUpdate) {
ArraySet<String> updatedPackages = new ArraySet<>();
- ArraySet<String> updatedPackagesDueToSecondaryDex = new ArraySet<>();
try {
boolean supportSecondaryDex = mInjector.supportSecondaryDex();
@@ -640,25 +640,12 @@
}
}
- pkgs = new ArraySet<>(pkgs);
+ pkgs = new ArrayList<>(pkgs);
pkgs.removeAll(unusedPackages);
}
}
- @Status int primaryResult = optimizePackages(pkgs, lowStorageThreshold,
- /*isForPrimaryDex=*/ true, updatedPackages, isPostBootUpdate);
- if (primaryResult != STATUS_OK) {
- return primaryResult;
- }
-
- if (!supportSecondaryDex) {
- return STATUS_OK;
- }
-
- @Status int secondaryResult = optimizePackages(pkgs, lowStorageThreshold,
- /*isForPrimaryDex*/ false, updatedPackagesDueToSecondaryDex,
- isPostBootUpdate);
- return secondaryResult;
+ return optimizePackages(pkgs, lowStorageThreshold, updatedPackages, isPostBootUpdate);
} finally {
// Always let the pinner service know about changes.
notifyPinService(updatedPackages);
@@ -670,8 +657,10 @@
}
@Status
- private int optimizePackages(ArraySet<String> pkgs, long lowStorageThreshold,
- boolean isForPrimaryDex, ArraySet<String> updatedPackages, boolean isPostBootUpdate) {
+ private int optimizePackages(List<String> pkgs, long lowStorageThreshold,
+ ArraySet<String> updatedPackages, boolean isPostBootUpdate) {
+ boolean supportSecondaryDex = mInjector.supportSecondaryDex();
+
for (String pkg : pkgs) {
int abortCode = abortIdleOptimizations(lowStorageThreshold);
if (abortCode != STATUS_OK) {
@@ -679,11 +668,23 @@
return abortCode;
}
- @DexOptResult int result = optimizePackage(pkg, isForPrimaryDex, isPostBootUpdate);
- if (result == PackageDexOptimizer.DEX_OPT_PERFORMED) {
+ @DexOptResult int primaryResult =
+ optimizePackage(pkg, true /* isForPrimaryDex */, isPostBootUpdate);
+ if (primaryResult == PackageDexOptimizer.DEX_OPT_PERFORMED) {
updatedPackages.add(pkg);
- } else if (result != PackageDexOptimizer.DEX_OPT_SKIPPED) {
- return convertPackageDexOptimizerStatusToInternal(result);
+ } else if (primaryResult != PackageDexOptimizer.DEX_OPT_SKIPPED) {
+ return convertPackageDexOptimizerStatusToInternal(primaryResult);
+ }
+
+ if (!supportSecondaryDex) {
+ continue;
+ }
+
+ @DexOptResult int secondaryResult =
+ optimizePackage(pkg, false /* isForPrimaryDex */, isPostBootUpdate);
+ if (secondaryResult != PackageDexOptimizer.DEX_OPT_PERFORMED
+ && secondaryResult != PackageDexOptimizer.DEX_OPT_SKIPPED) {
+ return convertPackageDexOptimizerStatusToInternal(secondaryResult);
}
}
return STATUS_OK;
diff --git a/services/core/java/com/android/server/pm/ComputerEngine.java b/services/core/java/com/android/server/pm/ComputerEngine.java
index 06e827a..54a10395 100644
--- a/services/core/java/com/android/server/pm/ComputerEngine.java
+++ b/services/core/java/com/android/server/pm/ComputerEngine.java
@@ -129,8 +129,6 @@
import com.android.server.pm.parsing.pkg.AndroidPackage;
import com.android.server.pm.parsing.pkg.AndroidPackageUtils;
import com.android.server.pm.permission.PermissionManagerServiceInternal;
-import com.android.server.pm.pkg.PackageState;
-import com.android.server.pm.pkg.PackageStateImpl;
import com.android.server.pm.pkg.PackageStateInternal;
import com.android.server.pm.pkg.PackageStateUtils;
import com.android.server.pm.pkg.PackageUserStateInternal;
@@ -2638,6 +2636,13 @@
public final boolean shouldFilterApplication(@Nullable PackageStateInternal ps,
int callingUid, @Nullable ComponentName component,
@PackageManager.ComponentType int componentType, int userId) {
+ if (Process.isSdkSandboxUid(callingUid)) {
+ int clientAppUid = Process.getAppUidForSdkSandboxUid(callingUid);
+ // SDK sandbox should be able to see it's client app
+ if (clientAppUid == UserHandle.getUid(userId, ps.getAppId())) {
+ return false;
+ }
+ }
// if we're in an isolated process, get the real calling UID
if (Process.isIsolated(callingUid)) {
callingUid = getIsolatedOwner(callingUid);
diff --git a/services/core/java/com/android/server/pm/CrossProfileAppsServiceImpl.java b/services/core/java/com/android/server/pm/CrossProfileAppsServiceImpl.java
index b307984..89f8be2 100644
--- a/services/core/java/com/android/server/pm/CrossProfileAppsServiceImpl.java
+++ b/services/core/java/com/android/server/pm/CrossProfileAppsServiceImpl.java
@@ -112,7 +112,9 @@
String callingFeatureId,
ComponentName component,
@UserIdInt int userId,
- boolean launchMainActivity) throws RemoteException {
+ boolean launchMainActivity,
+ IBinder targetTask,
+ Bundle options) throws RemoteException {
Objects.requireNonNull(callingPackage);
Objects.requireNonNull(component);
@@ -145,8 +147,12 @@
if (launchMainActivity) {
launchIntent.setAction(Intent.ACTION_MAIN);
launchIntent.addCategory(Intent.CATEGORY_LAUNCHER);
- launchIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK
- | Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED);
+ if (targetTask == null) {
+ launchIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK
+ | Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED);
+ } else {
+ launchIntent.addFlags(Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED);
+ }
// Only package name is set here, as opposed to component name, because intent action
// and category are ignored if component name is present while we are resolving intent.
launchIntent.setPackage(component.getPackageName());
@@ -170,15 +176,20 @@
}
verifyActivityCanHandleIntentAndExported(launchIntent, component, callingUid, userId);
+ // Always show the cross profile animation
+ if (options == null) {
+ options = ActivityOptions.makeOpenCrossProfileAppsAnimation().toBundle();
+ } else {
+ options.putAll(ActivityOptions.makeOpenCrossProfileAppsAnimation().toBundle());
+ }
+
launchIntent.setPackage(null);
launchIntent.setComponent(component);
mInjector.getActivityTaskManagerInternal().startActivityAsUser(
caller, callingPackage, callingFeatureId, launchIntent,
- /* resultTo= */ null,
- Intent.FLAG_ACTIVITY_NEW_TASK,
- launchMainActivity
- ? ActivityOptions.makeOpenCrossProfileAppsAnimation().toBundle()
- : null,
+ targetTask,
+ /* startFlags= */ 0,
+ options,
userId);
}
@@ -225,6 +236,13 @@
verifyActivityCanHandleIntent(launchIntent, callingUid, userId);
+ // Always show the cross profile animation
+ if (options == null) {
+ options = ActivityOptions.makeOpenCrossProfileAppsAnimation().toBundle();
+ } else {
+ options.putAll(ActivityOptions.makeOpenCrossProfileAppsAnimation().toBundle());
+ }
+
mInjector.getActivityTaskManagerInternal()
.startActivityAsUser(
caller,
diff --git a/services/core/java/com/android/server/pm/DexOptHelper.java b/services/core/java/com/android/server/pm/DexOptHelper.java
index 50b2e23..bb2ba5c 100644
--- a/services/core/java/com/android/server/pm/DexOptHelper.java
+++ b/services/core/java/com/android/server/pm/DexOptHelper.java
@@ -293,8 +293,8 @@
MetricsLogger.histogram(mPm.mContext, "opt_dialog_time_s", elapsedTimeSeconds);
}
- public ArraySet<String> getOptimizablePackages(@NonNull Computer snapshot) {
- ArraySet<String> pkgs = new ArraySet<>();
+ public List<String> getOptimizablePackages(@NonNull Computer snapshot) {
+ ArrayList<String> pkgs = new ArrayList<>();
mPm.forEachPackageState(snapshot, packageState -> {
final AndroidPackage pkg = packageState.getPkg();
if (pkg != null && mPm.mPackageDexOptimizer.canOptimizePackage(pkg)) {
diff --git a/services/core/java/com/android/server/pm/InitAndSystemPackageHelper.java b/services/core/java/com/android/server/pm/InitAppsHelper.java
similarity index 65%
rename from services/core/java/com/android/server/pm/InitAndSystemPackageHelper.java
rename to services/core/java/com/android/server/pm/InitAppsHelper.java
index 91750de..15f26e7 100644
--- a/services/core/java/com/android/server/pm/InitAndSystemPackageHelper.java
+++ b/services/core/java/com/android/server/pm/InitAppsHelper.java
@@ -32,6 +32,7 @@
import static com.android.server.pm.PackageManagerService.TAG;
import static com.android.server.pm.pkg.parsing.ParsingPackageUtils.PARSE_CHECK_MAX_SDK_VERSION;
+import android.annotation.NonNull;
import android.annotation.Nullable;
import android.content.pm.parsing.ApkLiteParseUtils;
import android.os.Environment;
@@ -61,14 +62,24 @@
* further cleanup and eventually all the installation/scanning related logic will go to another
* class.
*/
-final class InitAndSystemPackageHelper {
+final class InitAppsHelper {
private final PackageManagerService mPm;
-
private final List<ScanPartition> mDirsToScanAsSystem;
private final int mScanFlags;
private final int mSystemParseFlags;
private final int mSystemScanFlags;
private final InstallPackageHelper mInstallPackageHelper;
+ private final ApexManager mApexManager;
+ private final ExecutorService mExecutorService;
+ /* Tracks how long system scan took */
+ private long mSystemScanTime;
+ /* Track of the number of cached system apps */
+ private int mCachedSystemApps;
+ /* Track of the number of system apps */
+ private int mSystemPackagesCount;
+ private final boolean mIsDeviceUpgrading;
+ private final boolean mIsOnlyCoreApps;
+ private final List<ScanPartition> mSystemPartitions;
/**
* Tracks new system packages [received in an OTA] that we expect to
@@ -76,21 +87,33 @@
* are package location.
*/
private final ArrayMap<String, File> mExpectingBetter = new ArrayMap<>();
+ /* Tracks of any system packages that no longer exist that needs to be pruned. */
+ private final List<String> mPossiblyDeletedUpdatedSystemApps = new ArrayList<>();
+ // Tracks of stub packages that must either be replaced with full versions in the /data
+ // partition or be disabled.
+ private final List<String> mStubSystemApps = new ArrayList<>();
// TODO(b/198166813): remove PMS dependency
- InitAndSystemPackageHelper(PackageManagerService pm) {
+ InitAppsHelper(PackageManagerService pm, ApexManager apexManager,
+ InstallPackageHelper installPackageHelper,
+ List<ScanPartition> systemPartitions) {
mPm = pm;
- mInstallPackageHelper = new InstallPackageHelper(pm);
+ mApexManager = apexManager;
+ mInstallPackageHelper = installPackageHelper;
+ mSystemPartitions = systemPartitions;
mDirsToScanAsSystem = getSystemScanPartitions();
+ mIsDeviceUpgrading = mPm.isDeviceUpgrading();
+ mIsOnlyCoreApps = mPm.isOnlyCoreApps();
// Set flag to monitor and not change apk file paths when scanning install directories.
int scanFlags = SCAN_BOOTING | SCAN_INITIAL;
- if (mPm.isDeviceUpgrading() || mPm.isFirstBoot()) {
+ if (mIsDeviceUpgrading || mPm.isFirstBoot()) {
mScanFlags = scanFlags | SCAN_FIRST_BOOT_OR_UPGRADE;
} else {
mScanFlags = scanFlags;
}
mSystemParseFlags = mPm.getDefParseFlags() | ParsingPackageUtils.PARSE_IS_SYSTEM_DIR;
mSystemScanFlags = scanFlags | SCAN_AS_SYSTEM;
+ mExecutorService = ParallelPackageParser.makeExecutorService();
}
private List<File> getFrameworkResApkSplitFiles() {
@@ -118,7 +141,7 @@
private List<ScanPartition> getSystemScanPartitions() {
final List<ScanPartition> scanPartitions = new ArrayList<>();
- scanPartitions.addAll(mPm.mInjector.getSystemPartitions());
+ scanPartitions.addAll(mSystemPartitions);
scanPartitions.addAll(getApexScanPartitions());
Slog.d(TAG, "Directories scanned as system partitions: " + scanPartitions);
return scanPartitions;
@@ -126,8 +149,7 @@
private List<ScanPartition> getApexScanPartitions() {
final List<ScanPartition> scanPartitions = new ArrayList<>();
- final List<ApexManager.ActiveApexInfo> activeApexInfos =
- mPm.mApexManager.getActiveApexInfos();
+ final List<ApexManager.ActiveApexInfo> activeApexInfos = mApexManager.getActiveApexInfos();
for (int i = 0; i < activeApexInfos.size(); i++) {
final ScanPartition scanPartition = resolveApexToScanPartition(activeApexInfos.get(i));
if (scanPartition != null) {
@@ -144,117 +166,134 @@
if (apexInfo.preInstalledApexPath.getAbsolutePath().equals(
sp.getFolder().getAbsolutePath())
|| apexInfo.preInstalledApexPath.getAbsolutePath().startsWith(
- sp.getFolder().getAbsolutePath() + File.separator)) {
+ sp.getFolder().getAbsolutePath() + File.separator)) {
return new ScanPartition(apexInfo.apexDirectory, sp, SCAN_AS_APK_IN_APEX);
}
}
return null;
}
- public OverlayConfig initPackages(
- WatchedArrayMap<String, PackageSetting> packageSettings, int[] userIds,
- long startTime) {
- PackageParser2 packageParser = mPm.mInjector.getScanningCachingPackageParser();
-
- ExecutorService executorService = ParallelPackageParser.makeExecutorService();
+ /**
+ * Install apps from system dirs.
+ */
+ @GuardedBy({"mPm.mInstallLock", "mPm.mLock"})
+ public OverlayConfig initSystemApps(PackageParser2 packageParser,
+ WatchedArrayMap<String, PackageSetting> packageSettings,
+ int[] userIds, long startTime) {
// Prepare apex package info before scanning APKs, this information is needed when
// scanning apk in apex.
- mPm.mApexManager.scanApexPackagesTraced(packageParser, executorService);
+ mApexManager.scanApexPackagesTraced(packageParser, mExecutorService);
- scanSystemDirs(packageParser, executorService);
+ scanSystemDirs(packageParser, mExecutorService);
// Parse overlay configuration files to set default enable state, mutability, and
// priority of system overlays.
final ArrayMap<String, File> apkInApexPreInstalledPaths = new ArrayMap<>();
- for (ApexManager.ActiveApexInfo apexInfo : mPm.mApexManager.getActiveApexInfos()) {
- for (String packageName : mPm.mApexManager.getApksInApex(apexInfo.apexModuleName)) {
+ for (ApexManager.ActiveApexInfo apexInfo : mApexManager.getActiveApexInfos()) {
+ for (String packageName : mApexManager.getApksInApex(apexInfo.apexModuleName)) {
apkInApexPreInstalledPaths.put(packageName, apexInfo.preInstalledApexPath);
}
}
- OverlayConfig overlayConfig = OverlayConfig.initializeSystemInstance(
+ final OverlayConfig overlayConfig = OverlayConfig.initializeSystemInstance(
consumer -> mPm.forEachPackage(mPm.snapshotComputer(),
pkg -> consumer.accept(pkg, pkg.isSystem(),
- apkInApexPreInstalledPaths.get(pkg.getPackageName()))));
- // Prune any system packages that no longer exist.
- final List<String> possiblyDeletedUpdatedSystemApps = new ArrayList<>();
- // Stub packages must either be replaced with full versions in the /data
- // partition or be disabled.
- final List<String> stubSystemApps = new ArrayList<>();
+ apkInApexPreInstalledPaths.get(pkg.getPackageName()))));
- if (!mPm.isOnlyCoreApps()) {
+ if (!mIsOnlyCoreApps) {
// do this first before mucking with mPackages for the "expecting better" case
- updateStubSystemAppsList(stubSystemApps);
+ updateStubSystemAppsList(mStubSystemApps);
mInstallPackageHelper.prepareSystemPackageCleanUp(packageSettings,
- possiblyDeletedUpdatedSystemApps, mExpectingBetter, userIds);
+ mPossiblyDeletedUpdatedSystemApps, mExpectingBetter, userIds);
}
- final int cachedSystemApps = PackageCacher.sCachedPackageReadCount.get();
+ logSystemAppsScanningTime(startTime);
+ return overlayConfig;
+ }
+
+ @GuardedBy({"mPm.mInstallLock", "mPm.mLock"})
+ private void logSystemAppsScanningTime(long startTime) {
+ mCachedSystemApps = PackageCacher.sCachedPackageReadCount.get();
// Remove any shared userIDs that have no associated packages
mPm.mSettings.pruneSharedUsersLPw();
- final long systemScanTime = SystemClock.uptimeMillis() - startTime;
- final int systemPackagesCount = mPm.mPackages.size();
- Slog.i(TAG, "Finished scanning system apps. Time: " + systemScanTime
- + " ms, packageCount: " + systemPackagesCount
+ mSystemScanTime = SystemClock.uptimeMillis() - startTime;
+ mSystemPackagesCount = mPm.mPackages.size();
+ Slog.i(TAG, "Finished scanning system apps. Time: " + mSystemScanTime
+ + " ms, packageCount: " + mSystemPackagesCount
+ " , timePerPackage: "
- + (systemPackagesCount == 0 ? 0 : systemScanTime / systemPackagesCount)
- + " , cached: " + cachedSystemApps);
- if (mPm.isDeviceUpgrading() && systemPackagesCount > 0) {
+ + (mSystemPackagesCount == 0 ? 0 : mSystemScanTime / mSystemPackagesCount)
+ + " , cached: " + mCachedSystemApps);
+ if (mIsDeviceUpgrading && mSystemPackagesCount > 0) {
//CHECKSTYLE:OFF IndentationCheck
FrameworkStatsLog.write(FrameworkStatsLog.BOOT_TIME_EVENT_DURATION_REPORTED,
BOOT_TIME_EVENT_DURATION__EVENT__OTA_PACKAGE_MANAGER_SYSTEM_APP_AVG_SCAN_TIME,
- systemScanTime / systemPackagesCount);
+ mSystemScanTime / mSystemPackagesCount);
//CHECKSTYLE:ON IndentationCheck
}
+ }
- if (!mPm.isOnlyCoreApps()) {
+ /**
+ * Install apps/updates from data dir and fix system apps that are affected.
+ */
+ @GuardedBy({"mPm.mInstallLock", "mPm.mLock"})
+ public void initNonSystemApps(PackageParser2 packageParser, @NonNull int[] userIds,
+ long startTime) {
+ if (!mIsOnlyCoreApps) {
EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_PMS_DATA_SCAN_START,
SystemClock.uptimeMillis());
scanDirTracedLI(mPm.getAppInstallDir(), /* frameworkSplits= */ null, 0,
- mScanFlags | SCAN_REQUIRE_KNOWN, 0,
- packageParser, executorService);
-
+ mScanFlags | SCAN_REQUIRE_KNOWN,
+ packageParser, mExecutorService);
}
- List<Runnable> unfinishedTasks = executorService.shutdownNow();
+ List<Runnable> unfinishedTasks = mExecutorService.shutdownNow();
if (!unfinishedTasks.isEmpty()) {
throw new IllegalStateException("Not all tasks finished before calling close: "
+ unfinishedTasks);
}
-
- if (!mPm.isOnlyCoreApps()) {
- mInstallPackageHelper.cleanupDisabledPackageSettings(possiblyDeletedUpdatedSystemApps,
- userIds, mScanFlags);
- mInstallPackageHelper.checkExistingBetterPackages(mExpectingBetter,
- stubSystemApps, mSystemScanFlags, mSystemParseFlags);
-
- // Uncompress and install any stubbed system applications.
- // This must be done last to ensure all stubs are replaced or disabled.
- mInstallPackageHelper.installSystemStubPackages(stubSystemApps, mScanFlags);
-
- final int cachedNonSystemApps = PackageCacher.sCachedPackageReadCount.get()
- - cachedSystemApps;
-
- final long dataScanTime = SystemClock.uptimeMillis() - systemScanTime - startTime;
- final int dataPackagesCount = mPm.mPackages.size() - systemPackagesCount;
- Slog.i(TAG, "Finished scanning non-system apps. Time: " + dataScanTime
- + " ms, packageCount: " + dataPackagesCount
- + " , timePerPackage: "
- + (dataPackagesCount == 0 ? 0 : dataScanTime / dataPackagesCount)
- + " , cached: " + cachedNonSystemApps);
- if (mPm.isDeviceUpgrading() && dataPackagesCount > 0) {
- //CHECKSTYLE:OFF IndentationCheck
- FrameworkStatsLog.write(
- FrameworkStatsLog.BOOT_TIME_EVENT_DURATION_REPORTED,
- BOOT_TIME_EVENT_DURATION__EVENT__OTA_PACKAGE_MANAGER_DATA_APP_AVG_SCAN_TIME,
- dataScanTime / dataPackagesCount);
- //CHECKSTYLE:OFF IndentationCheck
- }
+ if (!mIsOnlyCoreApps) {
+ fixSystemPackages(userIds);
+ logNonSystemAppScanningTime(startTime);
}
mExpectingBetter.clear();
-
mPm.mSettings.pruneRenamedPackagesLPw();
- packageParser.close();
- return overlayConfig;
+ }
+
+ /**
+ * Clean up system packages now that some system package updates have been installed from
+ * the data dir. Also install system stub packages as the last step.
+ */
+ @GuardedBy({"mPm.mInstallLock", "mPm.mLock"})
+ private void fixSystemPackages(@NonNull int[] userIds) {
+ mInstallPackageHelper.cleanupDisabledPackageSettings(mPossiblyDeletedUpdatedSystemApps,
+ userIds, mScanFlags);
+ mInstallPackageHelper.checkExistingBetterPackages(mExpectingBetter,
+ mStubSystemApps, mSystemScanFlags, mSystemParseFlags);
+
+ // Uncompress and install any stubbed system applications.
+ // This must be done last to ensure all stubs are replaced or disabled.
+ mInstallPackageHelper.installSystemStubPackages(mStubSystemApps, mScanFlags);
+ }
+
+ @GuardedBy({"mPm.mInstallLock", "mPm.mLock"})
+ private void logNonSystemAppScanningTime(long startTime) {
+ final int cachedNonSystemApps = PackageCacher.sCachedPackageReadCount.get()
+ - mCachedSystemApps;
+
+ final long dataScanTime = SystemClock.uptimeMillis() - mSystemScanTime - startTime;
+ final int dataPackagesCount = mPm.mPackages.size() - mSystemPackagesCount;
+ Slog.i(TAG, "Finished scanning non-system apps. Time: " + dataScanTime
+ + " ms, packageCount: " + dataPackagesCount
+ + " , timePerPackage: "
+ + (dataPackagesCount == 0 ? 0 : dataScanTime / dataPackagesCount)
+ + " , cached: " + cachedNonSystemApps);
+ if (mIsDeviceUpgrading && dataPackagesCount > 0) {
+ //CHECKSTYLE:OFF IndentationCheck
+ FrameworkStatsLog.write(
+ FrameworkStatsLog.BOOT_TIME_EVENT_DURATION_REPORTED,
+ BOOT_TIME_EVENT_DURATION__EVENT__OTA_PACKAGE_MANAGER_DATA_APP_AVG_SCAN_TIME,
+ dataScanTime / dataPackagesCount);
+ //CHECKSTYLE:OFF IndentationCheck
+ }
}
/**
@@ -274,13 +313,13 @@
continue;
}
scanDirTracedLI(partition.getOverlayFolder(), /* frameworkSplits= */ null,
- mSystemParseFlags, mSystemScanFlags | partition.scanFlag, 0,
+ mSystemParseFlags, mSystemScanFlags | partition.scanFlag,
packageParser, executorService);
}
scanDirTracedLI(frameworkDir, null,
mSystemParseFlags,
- mSystemScanFlags | SCAN_NO_DEX | SCAN_AS_PRIVILEGED, 0,
+ mSystemScanFlags | SCAN_NO_DEX | SCAN_AS_PRIVILEGED,
packageParser, executorService);
if (!mPm.mPackages.containsKey("android")) {
throw new IllegalStateException(
@@ -292,11 +331,11 @@
if (partition.getPrivAppFolder() != null) {
scanDirTracedLI(partition.getPrivAppFolder(), /* frameworkSplits= */ null,
mSystemParseFlags,
- mSystemScanFlags | SCAN_AS_PRIVILEGED | partition.scanFlag, 0,
+ mSystemScanFlags | SCAN_AS_PRIVILEGED | partition.scanFlag,
packageParser, executorService);
}
scanDirTracedLI(partition.getAppFolder(), /* frameworkSplits= */ null,
- mSystemParseFlags, mSystemScanFlags | partition.scanFlag, 0,
+ mSystemParseFlags, mSystemScanFlags | partition.scanFlag,
packageParser, executorService);
}
}
@@ -315,7 +354,7 @@
@GuardedBy({"mPm.mInstallLock", "mPm.mLock"})
private void scanDirTracedLI(File scanDir, List<File> frameworkSplits,
int parseFlags, int scanFlags,
- long currentTime, PackageParser2 packageParser, ExecutorService executorService) {
+ PackageParser2 packageParser, ExecutorService executorService) {
Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "scanDir [" + scanDir.getAbsolutePath() + "]");
try {
if ((scanFlags & SCAN_AS_APK_IN_APEX) != 0) {
@@ -323,7 +362,7 @@
parseFlags |= PARSE_CHECK_MAX_SDK_VERSION;
}
mInstallPackageHelper.installPackagesFromDir(scanDir, frameworkSplits, parseFlags,
- scanFlags, currentTime, packageParser, executorService);
+ scanFlags, packageParser, executorService);
} finally {
Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
}
diff --git a/services/core/java/com/android/server/pm/InstallPackageHelper.java b/services/core/java/com/android/server/pm/InstallPackageHelper.java
index b39b24f..870a11a 100644
--- a/services/core/java/com/android/server/pm/InstallPackageHelper.java
+++ b/services/core/java/com/android/server/pm/InstallPackageHelper.java
@@ -3062,7 +3062,7 @@
final RemovePackageHelper removePackageHelper = new RemovePackageHelper(mPm);
removePackageHelper.removePackageLI(stubPkg, true /*chatty*/);
try {
- return scanSystemPackageTracedLI(scanFile, parseFlags, scanFlags, 0, null);
+ return scanSystemPackageTracedLI(scanFile, parseFlags, scanFlags, null);
} catch (PackageManagerException e) {
Slog.w(TAG, "Failed to install compressed system package:" + stubPkg.getPackageName(),
e);
@@ -3194,7 +3194,7 @@
| ParsingPackageUtils.PARSE_IS_SYSTEM_DIR;
@PackageManagerService.ScanFlags int scanFlags = mPm.getSystemPackageScanFlags(codePath);
final AndroidPackage pkg = scanSystemPackageTracedLI(
- codePath, parseFlags, scanFlags, 0 /*currentTime*/, null);
+ codePath, parseFlags, scanFlags, null);
PackageSetting pkgSetting = mPm.mSettings.getPackageLPr(pkg.getPackageName());
@@ -3368,7 +3368,7 @@
mRemovePackageHelper.removePackageLI(pkg, true);
try {
final File codePath = new File(pkg.getPath());
- scanSystemPackageTracedLI(codePath, 0, scanFlags, 0, null);
+ scanSystemPackageTracedLI(codePath, 0, scanFlags, null);
} catch (PackageManagerException e) {
Slog.e(TAG, "Failed to parse updated, ex-system package: "
+ e.getMessage());
@@ -3389,7 +3389,7 @@
@GuardedBy({"mPm.mInstallLock", "mPm.mLock"})
public void installPackagesFromDir(File scanDir, List<File> frameworkSplits, int parseFlags,
- int scanFlags, long currentTime, PackageParser2 packageParser,
+ int scanFlags, PackageParser2 packageParser,
ExecutorService executorService) {
final File[] files = scanDir.listFiles();
if (ArrayUtils.isEmpty(files)) {
@@ -3432,7 +3432,7 @@
parseResult.parsedPackage);
}
try {
- addForInitLI(parseResult.parsedPackage, parseFlags, scanFlags, currentTime,
+ addForInitLI(parseResult.parsedPackage, parseFlags, scanFlags,
null);
} catch (PackageManagerException e) {
errorCode = e.error;
@@ -3495,7 +3495,7 @@
try {
final AndroidPackage newPkg = scanSystemPackageTracedLI(
- scanFile, reparseFlags, rescanFlags, 0, null);
+ scanFile, reparseFlags, rescanFlags, null);
// We rescanned a stub, add it to the list of stubbed system packages
if (newPkg.isStub()) {
stubSystemApps.add(packageName);
@@ -3509,14 +3509,14 @@
/**
* Traces a package scan.
- * @see #scanSystemPackageLI(File, int, int, long, UserHandle)
+ * @see #scanSystemPackageLI(File, int, int, UserHandle)
*/
@GuardedBy({"mPm.mInstallLock", "mPm.mLock"})
public AndroidPackage scanSystemPackageTracedLI(File scanFile, final int parseFlags,
- int scanFlags, long currentTime, UserHandle user) throws PackageManagerException {
+ int scanFlags, UserHandle user) throws PackageManagerException {
Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "scanPackage [" + scanFile.toString() + "]");
try {
- return scanSystemPackageLI(scanFile, parseFlags, scanFlags, currentTime, user);
+ return scanSystemPackageLI(scanFile, parseFlags, scanFlags, user);
} finally {
Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
}
@@ -3528,7 +3528,7 @@
*/
@GuardedBy({"mPm.mInstallLock", "mPm.mLock"})
private AndroidPackage scanSystemPackageLI(File scanFile, int parseFlags, int scanFlags,
- long currentTime, UserHandle user) throws PackageManagerException {
+ UserHandle user) throws PackageManagerException {
if (DEBUG_INSTALL) Slog.d(TAG, "Parsing: " + scanFile);
Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "parsePackage");
@@ -3544,7 +3544,7 @@
PackageManagerService.renameStaticSharedLibraryPackage(parsedPackage);
}
- return addForInitLI(parsedPackage, parseFlags, scanFlags, currentTime, user);
+ return addForInitLI(parsedPackage, parseFlags, scanFlags, user);
}
/**
@@ -3563,11 +3563,11 @@
@GuardedBy({"mPm.mLock", "mPm.mInstallLock"})
private AndroidPackage addForInitLI(ParsedPackage parsedPackage,
@ParsingPackageUtils.ParseFlags int parseFlags,
- @PackageManagerService.ScanFlags int scanFlags, long currentTime,
+ @PackageManagerService.ScanFlags int scanFlags,
@Nullable UserHandle user) throws PackageManagerException {
final Pair<ScanResult, Boolean> scanResultPair = scanSystemPackageLI(
- parsedPackage, parseFlags, scanFlags, currentTime, user);
+ parsedPackage, parseFlags, scanFlags, user);
final ScanResult scanResult = scanResultPair.first;
boolean shouldHideSystemApp = scanResultPair.second;
if (scanResult.mSuccess) {
@@ -3762,7 +3762,7 @@
private Pair<ScanResult, Boolean> scanSystemPackageLI(ParsedPackage parsedPackage,
@ParsingPackageUtils.ParseFlags int parseFlags,
- @PackageManagerService.ScanFlags int scanFlags, long currentTime,
+ @PackageManagerService.ScanFlags int scanFlags,
@Nullable UserHandle user) throws PackageManagerException {
final boolean scanSystemPartition =
(parseFlags & ParsingPackageUtils.PARSE_IS_SYSTEM_DIR) != 0;
@@ -3950,7 +3950,7 @@
}
final ScanResult scanResult = scanPackageNewLI(parsedPackage, parseFlags,
- scanFlags | SCAN_UPDATE_SIGNATURE, currentTime, user, null);
+ scanFlags | SCAN_UPDATE_SIGNATURE, 0 /* currentTime */, user, null);
return new Pair<>(scanResult, shouldHideSystemApp);
}
diff --git a/services/core/java/com/android/server/pm/Installer.java b/services/core/java/com/android/server/pm/Installer.java
index 76b9830..45c5116 100644
--- a/services/core/java/com/android/server/pm/Installer.java
+++ b/services/core/java/com/android/server/pm/Installer.java
@@ -27,6 +27,7 @@
import android.os.CreateAppDataResult;
import android.os.IBinder;
import android.os.IInstalld;
+import android.os.ReconcileSdkDataArgs;
import android.os.RemoteException;
import android.os.ServiceManager;
import android.os.storage.CrateMetadata;
@@ -88,6 +89,14 @@
*/
public static final int PROFILE_ANALYSIS_DONT_OPTIMIZE_EMPTY_PROFILES = 3;
+ /**
+ * The results of {@code getOdexVisibility}. See
+ * {@link #getOdexVisibility(String, String, String)} for details.
+ */
+ public static final int ODEX_NOT_FOUND = 0;
+ public static final int ODEX_IS_PUBLIC = 1;
+ public static final int ODEX_IS_PRIVATE = 2;
+
public static final int FLAG_STORAGE_DE = IInstalld.FLAG_STORAGE_DE;
public static final int FLAG_STORAGE_CE = IInstalld.FLAG_STORAGE_CE;
@@ -215,6 +224,21 @@
return result;
}
+ static ReconcileSdkDataArgs buildReconcileSdkDataArgs(String uuid, String packageName,
+ List<String> subDirNames, int userId, int appId,
+ String seInfo, int flags) {
+ final ReconcileSdkDataArgs args = new ReconcileSdkDataArgs();
+ args.uuid = uuid;
+ args.packageName = packageName;
+ args.subDirNames = subDirNames;
+ args.userId = userId;
+ args.appId = appId;
+ args.previousAppId = 0;
+ args.seInfo = seInfo;
+ args.flags = flags;
+ return args;
+ }
+
public @NonNull CreateAppDataResult createAppData(@NonNull CreateAppDataArgs args)
throws InstallerException {
if (!checkBeforeRemote()) {
@@ -247,6 +271,18 @@
}
}
+ void reconcileSdkData(@NonNull ReconcileSdkDataArgs args)
+ throws InstallerException {
+ if (!checkBeforeRemote()) {
+ return;
+ }
+ try {
+ mInstalld.reconcileSdkData(args);
+ } catch (Exception e) {
+ throw InstallerException.from(e);
+ }
+ }
+
/**
* Class that collects multiple {@code installd} operations together in an
* attempt to more efficiently execute them in bulk.
@@ -838,6 +874,15 @@
}
}
+ /**
+ * Prepares the app profile for the package at the given path:
+ * <ul>
+ * <li>Creates the current profile for the given user ID, unless the user ID is
+ * {@code UserHandle.USER_NULL}.</li>
+ * <li>Merges the profile from the dex metadata file (if present) into the reference
+ * profile.</li>
+ * </ul>
+ */
public boolean prepareAppProfile(String pkg, @UserIdInt int userId, @AppIdInt int appId,
String profileName, String codePath, String dexMetadataPath) throws InstallerException {
if (!checkBeforeRemote()) return false;
@@ -988,6 +1033,33 @@
}
}
+ /**
+ * Returns the visibility of the optimized artifacts.
+ *
+ * @param packageName name of the package.
+ * @param apkPath path to the APK.
+ * @param instructionSet instruction set of the optimized artifacts.
+ * @param outputPath path to the directory that contains the optimized artifacts (i.e., the
+ * directory that {@link #dexopt} outputs to).
+ *
+ * @return {@link #ODEX_NOT_FOUND} if the optimized artifacts are not found, or
+ * {@link #ODEX_IS_PUBLIC} if the optimized artifacts are accessible by all apps, or
+ * {@link #ODEX_IS_PRIVATE} if the optimized artifacts are only accessible by this app.
+ *
+ * @throws InstallerException if failed to get the visibility of the optimized artifacts.
+ */
+ public int getOdexVisibility(String packageName, String apkPath, String instructionSet,
+ String outputPath) throws InstallerException {
+ if (!checkBeforeRemote()) return -1;
+ BlockGuard.getVmPolicy().onPathAccess(apkPath);
+ BlockGuard.getVmPolicy().onPathAccess(outputPath);
+ try {
+ return mInstalld.getOdexVisibility(packageName, apkPath, instructionSet, outputPath);
+ } catch (Exception e) {
+ throw InstallerException.from(e);
+ }
+ }
+
public static class InstallerException extends Exception {
public InstallerException(String detailMessage) {
super(detailMessage);
diff --git a/services/core/java/com/android/server/pm/PackageDexOptimizer.java b/services/core/java/com/android/server/pm/PackageDexOptimizer.java
index 69d4987..27c6d9b 100644
--- a/services/core/java/com/android/server/pm/PackageDexOptimizer.java
+++ b/services/core/java/com/android/server/pm/PackageDexOptimizer.java
@@ -319,28 +319,42 @@
String profileName = ArtManager.getProfileName(
i == 0 ? null : pkg.getSplitNames()[i - 1]);
+ final boolean isUsedByOtherApps = options.isDexoptAsSharedLibrary()
+ || packageUseInfo.isUsedByOtherApps(path);
+ String compilerFilter = getRealCompilerFilter(pkg, options.getCompilerFilter());
+ // If the app is used by other apps, we must not use the existing profile because it
+ // may contain user data, unless the profile is newly created on install.
+ final boolean resetProfile = isProfileGuidedCompilerFilter(compilerFilter)
+ && isUsedByOtherApps
+ && options.getCompilationReason() != PackageManagerService.REASON_INSTALL;
String dexMetadataPath = null;
- if (options.isDexoptInstallWithDexMetadata()) {
+ if (options.isDexoptInstallWithDexMetadata() || resetProfile) {
File dexMetadataFile = DexMetadataHelper.findDexMetadataForFile(new File(path));
dexMetadataPath = dexMetadataFile == null
? null : dexMetadataFile.getAbsolutePath();
}
- final boolean isUsedByOtherApps = options.isDexoptAsSharedLibrary()
- || packageUseInfo.isUsedByOtherApps(path);
- final String compilerFilter = getRealCompilerFilter(pkg,
- options.getCompilerFilter(), isUsedByOtherApps);
// If we don't have to check for profiles updates assume
// PROFILE_ANALYSIS_DONT_OPTIMIZE_SMALL_DELTA which will be a no-op with respect to
// profiles.
- final int profileAnalysisResult = options.isCheckForProfileUpdates()
- ? analyseProfiles(pkg, sharedGid, profileName, compilerFilter)
- : PROFILE_ANALYSIS_DONT_OPTIMIZE_SMALL_DELTA;
+ int profileAnalysisResult = PROFILE_ANALYSIS_DONT_OPTIMIZE_SMALL_DELTA;
+ if (resetProfile) {
+ if (!resetProfile(pkg, profileName, path, dexMetadataPath)) {
+ // Fall back to use the shared filter.
+ compilerFilter =
+ PackageManagerServiceCompilerMapping.getCompilerFilterForReason(
+ PackageManagerService.REASON_SHARED);
+ }
+ } else if (options.isCheckForProfileUpdates()) {
+ profileAnalysisResult =
+ analyseProfiles(pkg, sharedGid, profileName, compilerFilter);
+ }
// Get the dexopt flags after getRealCompilerFilter to make sure we get the correct
// flags.
- final int dexoptFlags = getDexFlags(pkg, pkgSetting, compilerFilter, options);
+ final int dexoptFlags = getDexFlags(pkg, pkgSetting, compilerFilter, resetProfile,
+ options);
for (String dexCodeIsa : dexCodeInstructionSets) {
int newResult = dexOptPath(pkg, pkgSetting, path, dexCodeIsa, compilerFilter,
@@ -391,6 +405,30 @@
}
/**
+ * Resets the profiles of the dex file at {@code path} belonging to the package {@code pkg} to
+ * the initial state as if the package is newly installed. Returns true on success, or false
+ * otherwise.
+ */
+ @GuardedBy("mInstallLock")
+ private boolean resetProfile(AndroidPackage pkg, String profileName, String path,
+ @Nullable String dexMetadataPath) {
+ if (dexMetadataPath != null) {
+ try {
+ mInstaller.clearAppProfiles(pkg.getPackageName(), profileName);
+ final int appId = UserHandle.getAppId(pkg.getUid());
+ mInstaller.prepareAppProfile(pkg.getPackageName(), UserHandle.USER_NULL,
+ appId, profileName, path, dexMetadataPath);
+ return true;
+ } catch (InstallerException e) {
+ Slog.w(TAG, "Failed to reset profile", e);
+ return false;
+ }
+ } else {
+ return false;
+ }
+ }
+
+ /**
* Performs dexopt on the {@code path} belonging to the package {@code pkg}.
*
* @return
@@ -405,15 +443,15 @@
String classLoaderContext, int dexoptFlags, int uid,
CompilerStats.PackageStats packageStats, boolean downgrade, String profileName,
String dexMetadataPath, int compilationReason) {
- int dexoptNeeded = getDexoptNeeded(path, isa, compilerFilter, classLoaderContext,
- profileAnalysisResult, downgrade);
+ String oatDir = getPackageOatDirIfSupported(pkg,
+ pkgSetting.getTransientState().isUpdatedSystemApp());
+
+ int dexoptNeeded = getDexoptNeeded(pkg.getPackageName(), path, isa, compilerFilter,
+ classLoaderContext, profileAnalysisResult, downgrade, dexoptFlags, oatDir);
if (Math.abs(dexoptNeeded) == DexFile.NO_DEXOPT_NEEDED) {
return DEX_OPT_SKIPPED;
}
- String oatDir = getPackageOatDirIfSupported(pkg,
- pkgSetting.getTransientState().isUpdatedSystemApp());
-
Log.i(TAG, "Running dexopt (dexoptNeeded=" + dexoptNeeded + ") on: " + path
+ " pkg=" + pkg.getPackageName() + " isa=" + isa
+ " dexoptFlags=" + printDexoptFlags(dexoptFlags)
@@ -456,6 +494,7 @@
/**
* Perform dexopt (if needed) on a system server code path).
*/
+ @GuardedBy("mInstallLock")
@DexOptResult
public int dexoptSystemServerPath(
String dexPath, PackageDexUsage.DexUseInfo dexUseInfo, DexoptOptions options) {
@@ -466,12 +505,15 @@
int result = DEX_OPT_SKIPPED;
for (String isa : dexUseInfo.getLoaderIsas()) {
int dexoptNeeded = getDexoptNeeded(
+ PackageManagerService.PLATFORM_PACKAGE_NAME,
dexPath,
isa,
options.getCompilerFilter(),
dexUseInfo.getClassLoaderContext(),
PROFILE_ANALYSIS_DONT_OPTIMIZE_EMPTY_PROFILES,
- /* downgrade= */ false);
+ /* downgrade= */ false,
+ dexoptFlags,
+ /* oatDir= */ null);
if (dexoptNeeded == DexFile.NO_DEXOPT_NEEDED) {
continue;
@@ -714,7 +756,7 @@
}
/**
- * Returns the compiler filter that should be used to optimize the package code.
+ * Returns the compiler filter that should be used to optimize the secondary dex.
* The target filter will be updated if the package code is used by other apps
* or if it has the safe mode flag set.
*/
@@ -754,12 +796,12 @@
}
/**
- * Returns the compiler filter that should be used to optimize the package code.
- * The target filter will be updated if the package code is used by other apps
- * or if it has the safe mode flag set.
+ * Returns the compiler filter that should be used to optimize the primary dex.
+ * The target filter will be updated if the package has the safe mode flag set. Note that this
+ * method does NOT take other app use into account. The caller should be responsible for
+ * handling the case where the package code is used by other apps.
*/
- private String getRealCompilerFilter(AndroidPackage pkg, String targetCompilerFilter,
- boolean isUsedByOtherApps) {
+ private String getRealCompilerFilter(AndroidPackage pkg, String targetCompilerFilter) {
// When an app or priv app is configured to run out of box, only verify it.
if (pkg.isUseEmbeddedDex()
|| (pkg.isPrivileged()
@@ -783,12 +825,6 @@
return getSafeModeCompilerFilter(targetCompilerFilter);
}
- if (isProfileGuidedCompilerFilter(targetCompilerFilter) && isUsedByOtherApps) {
- // If the dex files is used by other apps, apply the shared filter.
- return PackageManagerServiceCompilerMapping.getCompilerFilterForReason(
- PackageManagerService.REASON_SHARED);
- }
-
return targetCompilerFilter;
}
@@ -799,14 +835,16 @@
private int getDexFlags(ApplicationInfo info, String compilerFilter, DexoptOptions options) {
return getDexFlags((info.flags & ApplicationInfo.FLAG_DEBUGGABLE) != 0,
info.getHiddenApiEnforcementPolicy(), info.splitDependencies,
- info.requestsIsolatedSplitLoading(), compilerFilter, options);
+ info.requestsIsolatedSplitLoading(), compilerFilter, false /* resetProfile */,
+ options);
}
+
private int getDexFlags(AndroidPackage pkg, @NonNull PackageStateInternal pkgSetting,
- String compilerFilter, DexoptOptions options) {
+ String compilerFilter, boolean resetProfile, DexoptOptions options) {
return getDexFlags(pkg.isDebuggable(),
AndroidPackageUtils.getHiddenApiEnforcementPolicy(pkg, pkgSetting),
pkg.getSplitDependencies(), pkg.isIsolatedSplitLoading(), compilerFilter,
- options);
+ resetProfile, options);
}
/**
@@ -815,13 +853,15 @@
*/
private int getDexFlags(boolean debuggable, int hiddenApiEnforcementPolicy,
SparseArray<int[]> splitDependencies, boolean requestsIsolatedSplitLoading,
- String compilerFilter, DexoptOptions options) {
+ String compilerFilter, boolean resetProfile, DexoptOptions options) {
// Profile guide compiled oat files should not be public unles they are based
// on profiles from dex metadata archives.
// The flag isDexoptInstallWithDexMetadata applies only on installs when we know that
// the user does not have an existing profile.
+ // The flag resetProfile applies only when the existing profile is already reset.
boolean isProfileGuidedFilter = isProfileGuidedCompilerFilter(compilerFilter);
- boolean isPublic = !isProfileGuidedFilter || options.isDexoptInstallWithDexMetadata();
+ boolean isPublic = !isProfileGuidedFilter || options.isDexoptInstallWithDexMetadata()
+ || resetProfile;
int profileFlag = isProfileGuidedFilter ? DEXOPT_PROFILE_GUIDED : 0;
// Some apps are executed with restrictions on hidden API usage. If this app is one
// of them, pass a flag to dexopt to enable the same restrictions during compilation.
@@ -866,8 +906,19 @@
* Assesses if there's a need to perform dexopt on {@code path} for the given
* configuration (isa, compiler filter, profile).
*/
- private int getDexoptNeeded(String path, String isa, String compilerFilter,
- String classLoaderContext, int profileAnalysisResult, boolean downgrade) {
+ @GuardedBy("mInstallLock")
+ private int getDexoptNeeded(String packageName, String path, String isa, String compilerFilter,
+ String classLoaderContext, int profileAnalysisResult, boolean downgrade,
+ int dexoptFlags, String oatDir) {
+ final boolean shouldBePublic = (dexoptFlags & DEXOPT_PUBLIC) != 0;
+ // If the artifacts should be public while the current artifacts are not, we should
+ // re-compile anyway.
+ if (shouldBePublic && isOdexPrivate(packageName, path, isa, oatDir)) {
+ // Ensure compilation by pretending a compiler filter change on the apk/odex location
+ // (the reason for the '-'. A positive value means the 'oat' location).
+ return adjustDexoptNeeded(-DexFile.DEX2OAT_FOR_FILTER);
+ }
+
int dexoptNeeded;
try {
// A profile guided optimizations with an empty profile is essentially 'verify' and
@@ -901,6 +952,18 @@
return compilerFilter.endsWith("-profile");
}
+ /** Returns true if the current artifacts of the app are private to the app itself. */
+ @GuardedBy("mInstallLock")
+ private boolean isOdexPrivate(String packageName, String path, String isa, String oatDir) {
+ try {
+ return mInstaller.getOdexVisibility(packageName, path, isa, oatDir)
+ == Installer.ODEX_IS_PRIVATE;
+ } catch (Exception e) {
+ Slog.w(TAG, "Failed to get odex visibility for " + path, e);
+ return false;
+ }
+ }
+
/**
* Checks if there is an update on the profile information of the {@code pkg}.
* If the compiler filter is not profile guided the method returns a safe default:
diff --git a/services/core/java/com/android/server/pm/PackageInstallerService.java b/services/core/java/com/android/server/pm/PackageInstallerService.java
index 4e702e2..aa5f39f 100644
--- a/services/core/java/com/android/server/pm/PackageInstallerService.java
+++ b/services/core/java/com/android/server/pm/PackageInstallerService.java
@@ -1332,7 +1332,7 @@
private String getDeviceOwnerDeletedPackageMsg() {
DevicePolicyManager dpm = mContext.getSystemService(DevicePolicyManager.class);
- return dpm.getString(PACKAGE_DELETED_BY_DO,
+ return dpm.getResources().getString(PACKAGE_DELETED_BY_DO,
() -> mContext.getString(R.string.package_updated_device_owner));
}
diff --git a/services/core/java/com/android/server/pm/PackageInstallerSession.java b/services/core/java/com/android/server/pm/PackageInstallerSession.java
index 68be64f..beb1986 100644
--- a/services/core/java/com/android/server/pm/PackageInstallerSession.java
+++ b/services/core/java/com/android/server/pm/PackageInstallerSession.java
@@ -29,6 +29,7 @@
import static android.content.pm.PackageManager.INSTALL_FAILED_INVALID_APK;
import static android.content.pm.PackageManager.INSTALL_FAILED_MEDIA_UNAVAILABLE;
import static android.content.pm.PackageManager.INSTALL_FAILED_MISSING_SPLIT;
+import static android.content.pm.PackageManager.INSTALL_FROM_ADB;
import static android.content.pm.PackageManager.INSTALL_PARSE_FAILED_NO_CERTIFICATES;
import static android.content.pm.PackageManager.INSTALL_STAGED;
import static android.content.pm.PackageManager.INSTALL_SUCCEEDED;
@@ -956,12 +957,17 @@
"DataLoader installation of APEX modules is not allowed.");
}
- if (isSystemDataLoaderInstallation() && mContext.checkCallingOrSelfPermission(
- Manifest.permission.USE_SYSTEM_DATA_LOADERS)
- != PackageManager.PERMISSION_GRANTED) {
- throw new SecurityException("You need the "
- + "com.android.permission.USE_SYSTEM_DATA_LOADERS permission "
- + "to use system data loaders");
+ if (isSystemDataLoaderInstallation()) {
+ if (mContext.checkCallingOrSelfPermission(
+ Manifest.permission.USE_SYSTEM_DATA_LOADERS)
+ != PackageManager.PERMISSION_GRANTED) {
+ throw new SecurityException("You need the "
+ + "com.android.permission.USE_SYSTEM_DATA_LOADERS permission "
+ + "to use system data loaders");
+ }
+
+ // All installations using system dataloaders marked as ADB.
+ this.params.installFlags |= INSTALL_FROM_ADB;
}
}
@@ -4288,9 +4294,9 @@
private static String getDeviceOwnerInstalledPackageMsg(Context context, boolean update) {
DevicePolicyManager dpm = context.getSystemService(DevicePolicyManager.class);
return update
- ? dpm.getString(PACKAGE_UPDATED_BY_DO,
+ ? dpm.getResources().getString(PACKAGE_UPDATED_BY_DO,
() -> context.getString(R.string.package_updated_device_owner))
- : dpm.getString(PACKAGE_INSTALLED_BY_DO,
+ : dpm.getResources().getString(PACKAGE_INSTALLED_BY_DO,
() -> context.getString(R.string.package_installed_device_owner));
}
diff --git a/services/core/java/com/android/server/pm/PackageManagerLocal.java b/services/core/java/com/android/server/pm/PackageManagerLocal.java
index 7b76567..39cc37e 100644
--- a/services/core/java/com/android/server/pm/PackageManagerLocal.java
+++ b/services/core/java/com/android/server/pm/PackageManagerLocal.java
@@ -16,8 +16,16 @@
package com.android.server.pm;
+import android.annotation.IntDef;
+import android.annotation.NonNull;
+import android.annotation.Nullable;
import android.annotation.SystemApi;
+import java.io.IOException;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.util.List;
+
/**
* In-process API for server side PackageManager related infrastructure.
*
@@ -28,4 +36,48 @@
*/
@SystemApi(client = SystemApi.Client.SYSTEM_SERVER)
public interface PackageManagerLocal {
+
+ /**
+ * Indicates if operation should include device encrypted storage.
+ */
+ int FLAG_STORAGE_DE = Installer.FLAG_STORAGE_DE;
+ /**
+ * Indicates if operation should include credential encrypted storage.
+ */
+ int FLAG_STORAGE_CE = Installer.FLAG_STORAGE_CE;
+
+ /**
+ * Constants for use with {@link #reconcileSdkData} to specify which storage areas should be
+ * included for operation.
+ *
+ * @hide
+ */
+ @IntDef(prefix = "FLAG_STORAGE_", value = {
+ FLAG_STORAGE_DE,
+ FLAG_STORAGE_CE,
+ })
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface StorageFlags {}
+
+ /**
+ * Reconcile sdk data sub-directories for the given {@code packagName}.
+ *
+ * Sub directories are created if they do not exist already. If there is an existing per-
+ * sdk directory that is missing from {@code subDirNames}, then it is removed.
+ *
+ * Sdk package path is created if it doesn't exist before creating per-sdk directories.
+ *
+ * @param volumeUuid the volume in which the sdk data should be prepared.
+ * @param packageName package name of the app for which sdk data directory will be prepared.
+ * @param subDirNames names of sub directories that should be reconciled against.
+ * @param userId id of the user to whom the package belongs to.
+ * @param appId id of the package.
+ * @param previousAppId previous id of the package if package is being updated.
+ * @param flags flags from StorageManager to indicate which storage areas should be included.
+ * @param seInfo seInfo tag to be used for selinux policy.
+ * @throws IOException If any error occurs during the operation.
+ */
+ void reconcileSdkData(@Nullable String volumeUuid, @NonNull String packageName,
+ @NonNull List<String> subDirNames, int userId, int appId, int previousAppId,
+ @NonNull String seInfo, @StorageFlags int flags) throws IOException;
}
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index 67056ea..b1b05be 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -132,6 +132,7 @@
import android.os.ParcelableException;
import android.os.PersistableBundle;
import android.os.Process;
+import android.os.ReconcileSdkDataArgs;
import android.os.RemoteException;
import android.os.ResultReceiver;
import android.os.ServiceManager;
@@ -228,7 +229,6 @@
import com.android.server.pm.verify.domain.DomainVerificationManagerInternal;
import com.android.server.pm.verify.domain.DomainVerificationService;
import com.android.server.pm.verify.domain.proxy.DomainVerificationProxy;
-import com.android.server.pm.verify.domain.proxy.DomainVerificationProxyV1;
import com.android.server.sdksandbox.SdkSandboxManagerLocal;
import com.android.server.storage.DeviceStorageMonitorInternal;
import com.android.server.utils.SnapshotCache;
@@ -935,7 +935,7 @@
private final BroadcastHelper mBroadcastHelper;
private final RemovePackageHelper mRemovePackageHelper;
private final DeletePackageHelper mDeletePackageHelper;
- private final InitAndSystemPackageHelper mInitAndSystemPackageHelper;
+ private final InitAppsHelper mInitAppsHelper;
private final AppDataHelper mAppDataHelper;
private final InstallPackageHelper mInstallPackageHelper;
private final PreferredActivityHelper mPreferredActivityHelper;
@@ -1670,7 +1670,7 @@
mAppDataHelper = testParams.appDataHelper;
mInstallPackageHelper = testParams.installPackageHelper;
mRemovePackageHelper = testParams.removePackageHelper;
- mInitAndSystemPackageHelper = testParams.initAndSystemPackageHelper;
+ mInitAppsHelper = testParams.initAndSystemPackageHelper;
mDeletePackageHelper = testParams.deletePackageHelper;
mPreferredActivityHelper = testParams.preferredActivityHelper;
mResolveIntentHelper = testParams.resolveIntentHelper;
@@ -1820,7 +1820,8 @@
mAppDataHelper = new AppDataHelper(this);
mInstallPackageHelper = new InstallPackageHelper(this, mAppDataHelper);
mRemovePackageHelper = new RemovePackageHelper(this, mAppDataHelper);
- mInitAndSystemPackageHelper = new InitAndSystemPackageHelper(this);
+ mInitAppsHelper = new InitAppsHelper(this, mApexManager, mInstallPackageHelper,
+ mInjector.getSystemPartitions());
mDeletePackageHelper = new DeletePackageHelper(this, mRemovePackageHelper,
mAppDataHelper);
mSharedLibraries.setDeletePackageHelper(mDeletePackageHelper);
@@ -1955,8 +1956,11 @@
mIsEngBuild, mIsUserDebugBuild, mIncrementalVersion);
final int[] userIds = mUserManager.getUserIds();
- mOverlayConfig = mInitAndSystemPackageHelper.initPackages(packageSettings,
- userIds, startTime);
+ PackageParser2 packageParser = mInjector.getScanningCachingPackageParser();
+ mOverlayConfig = mInitAppsHelper.initSystemApps(packageParser, packageSettings, userIds,
+ startTime);
+ mInitAppsHelper.initNonSystemApps(packageParser, userIds, startTime);
+ packageParser.close();
// Resolve the storage manager.
mStorageManagerPackage = getStorageManagerPackageName(computer);
@@ -6032,6 +6036,22 @@
}
private class PackageManagerLocalImpl implements PackageManagerLocal {
+ @Override
+ public void reconcileSdkData(@Nullable String volumeUuid, @NonNull String packageName,
+ @NonNull List<String> subDirNames, int userId, int appId, int previousAppId,
+ @NonNull String seInfo, int flags) throws IOException {
+ synchronized (mInstallLock) {
+ ReconcileSdkDataArgs args = mInstaller.buildReconcileSdkDataArgs(volumeUuid,
+ packageName, subDirNames, userId, appId, seInfo,
+ flags);
+ args.previousAppId = previousAppId;
+ try {
+ mInstaller.reconcileSdkData(args);
+ } catch (InstallerException e) {
+ throw new IOException(e.getMessage());
+ }
+ }
+ }
}
private class PackageManagerInternalImpl extends PackageManagerInternalBase {
@@ -7013,7 +7033,7 @@
}
boolean isExpectingBetter(String packageName) {
- return mInitAndSystemPackageHelper.isExpectingBetter(packageName);
+ return mInitAppsHelper.isExpectingBetter(packageName);
}
int getDefParseFlags() {
@@ -7112,13 +7132,12 @@
}
boolean isOverlayMutable(String packageName) {
- return (mOverlayConfig != null ? mOverlayConfig
- : OverlayConfig.getSystemInstance()).isMutable(packageName);
+ return mOverlayConfig.isMutable(packageName);
}
@ScanFlags int getSystemPackageScanFlags(File codePath) {
List<ScanPartition> dirsToScanAsSystem =
- mInitAndSystemPackageHelper.getDirsToScanAsSystem();
+ mInitAppsHelper.getDirsToScanAsSystem();
@PackageManagerService.ScanFlags int scanFlags = SCAN_AS_SYSTEM;
for (int i = dirsToScanAsSystem.size() - 1; i >= 0; i--) {
ScanPartition partition = dirsToScanAsSystem.get(i);
@@ -7136,7 +7155,7 @@
Pair<Integer, Integer> getSystemPackageRescanFlagsAndReparseFlags(File scanFile,
int systemScanFlags, int systemParseFlags) {
List<ScanPartition> dirsToScanAsSystem =
- mInitAndSystemPackageHelper.getDirsToScanAsSystem();
+ mInitAppsHelper.getDirsToScanAsSystem();
@ParsingPackageUtils.ParseFlags int reparseFlags = 0;
@PackageManagerService.ScanFlags int rescanFlags = 0;
for (int i1 = dirsToScanAsSystem.size() - 1; i1 >= 0; i1--) {
diff --git a/services/core/java/com/android/server/pm/PackageManagerServiceTestParams.java b/services/core/java/com/android/server/pm/PackageManagerServiceTestParams.java
index 5bdda0b..e466fe2 100644
--- a/services/core/java/com/android/server/pm/PackageManagerServiceTestParams.java
+++ b/services/core/java/com/android/server/pm/PackageManagerServiceTestParams.java
@@ -109,7 +109,7 @@
public AppDataHelper appDataHelper;
public InstallPackageHelper installPackageHelper;
public RemovePackageHelper removePackageHelper;
- public InitAndSystemPackageHelper initAndSystemPackageHelper;
+ public InitAppsHelper initAndSystemPackageHelper;
public DeletePackageHelper deletePackageHelper;
public PreferredActivityHelper preferredActivityHelper;
public ResolveIntentHelper resolveIntentHelper;
diff --git a/services/core/java/com/android/server/pm/Settings.java b/services/core/java/com/android/server/pm/Settings.java
index 6ccaae1..698dbe9 100644
--- a/services/core/java/com/android/server/pm/Settings.java
+++ b/services/core/java/com/android/server/pm/Settings.java
@@ -62,7 +62,6 @@
import android.os.Message;
import android.os.PatternMatcher;
import android.os.PersistableBundle;
-import android.os.Process;
import android.os.SELinux;
import android.os.SystemClock;
import android.os.Trace;
@@ -408,8 +407,6 @@
int[] excludedUserIds;
}
- private static int mFirstAvailableUid = Process.FIRST_APPLICATION_UID;
-
/** Map from volume UUID to {@link VersionInfo} */
@Watched
private final WatchedArrayMap<String, VersionInfo> mVersion = new WatchedArrayMap<>();
@@ -472,10 +469,8 @@
@Watched
final WatchedArrayMap<String, SharedUserSetting> mSharedUsers = new WatchedArrayMap<>();
- @Watched
+ @Watched(manual = true)
private final AppIdSettingMap mAppIds;
- @Watched
- private final AppIdSettingMap mOtherAppIds;
// For reading/writing settings file.
@Watched
@@ -565,7 +560,6 @@
mCrossProfileIntentResolvers.registerObserver(mObserver);
mSharedUsers.registerObserver(mObserver);
mAppIds.registerObserver(mObserver);
- mOtherAppIds.registerObserver(mObserver);
mRenamedPackages.registerObserver(mObserver);
mNextAppLinkGeneration.registerObserver(mObserver);
mDefaultBrowserApp.registerObserver(mObserver);
@@ -592,7 +586,6 @@
mLock = new PackageManagerTracedLock();
mPackages.putAll(pkgSettings);
mAppIds = new AppIdSettingMap();
- mOtherAppIds = new AppIdSettingMap();
mSystemDir = null;
mPermissions = null;
mRuntimePermissionsPersistence = null;
@@ -629,7 +622,6 @@
mLock = lock;
mAppIds = new AppIdSettingMap();
- mOtherAppIds = new AppIdSettingMap();
mPermissions = new LegacyPermissionSettings(lock);
mRuntimePermissionsPersistence = new RuntimePermissionPersistence(
runtimePermissionsPersistence, new Consumer<Integer>() {
@@ -710,7 +702,6 @@
mCrossProfileIntentResolvers, r.mCrossProfileIntentResolvers);
mSharedUsers.snapshot(r.mSharedUsers);
mAppIds = r.mAppIds.snapshot();
- mOtherAppIds = r.mOtherAppIds.snapshot();
WatchedArrayList.snapshot(
mPastSignatures, r.mPastSignatures);
WatchedArrayMap.snapshot(
@@ -782,7 +773,7 @@
SharedUserSetting s = mSharedUsers.get(name);
if (s == null && create) {
s = new SharedUserSetting(name, pkgFlags, pkgPrivateFlags);
- s.mAppId = acquireAndRegisterNewAppIdLPw(s);
+ s.mAppId = mAppIds.acquireAndRegisterNewAppId(s);
if (s.mAppId < 0) {
// < 0 means we couldn't assign a userid; throw exception
throw new PackageManagerException(INSTALL_FAILED_INSUFFICIENT_STORAGE,
@@ -890,7 +881,7 @@
pkgPrivateFlags, 0 /*userId*/, usesSdkLibraries, usesSdkLibrariesVersions,
usesStaticLibraries, usesStaticLibrariesVersions, mimeGroups, domainSetId);
p.setAppId(uid);
- if (registerExistingAppIdLPw(uid, p, name)) {
+ if (mAppIds.registerExistingAppId(uid, p, name)) {
mPackages.put(name, p);
return p;
}
@@ -909,7 +900,7 @@
}
s = new SharedUserSetting(name, pkgFlags, pkgPrivateFlags);
s.mAppId = uid;
- if (registerExistingAppIdLPw(uid, s, name)) {
+ if (mAppIds.registerExistingAppId(uid, s, name)) {
mSharedUsers.put(name, s);
return s;
}
@@ -1210,11 +1201,11 @@
final boolean createdNew;
if (p.getAppId() == 0 || forceNew) {
// Assign new user ID
- p.setAppId(acquireAndRegisterNewAppIdLPw(p));
+ p.setAppId(mAppIds.acquireAndRegisterNewAppId(p));
createdNew = true;
} else {
// Add new setting to list of user IDs
- createdNew = registerExistingAppIdLPw(p.getAppId(), p, p.getPackageName());
+ createdNew = mAppIds.registerExistingAppId(p.getAppId(), p, p.getPackageName());
}
if (p.getAppId() < 0) {
PackageManagerService.reportSettingsProblem(Log.WARN,
@@ -1304,11 +1295,11 @@
Object userIdPs = getSettingLPr(p.getAppId());
if (sharedUser == null) {
if (userIdPs != null && userIdPs != p) {
- replaceAppIdLPw(p.getAppId(), p);
+ mAppIds.replaceSetting(p.getAppId(), p);
}
} else {
if (userIdPs != null && userIdPs != sharedUser) {
- replaceAppIdLPw(p.getAppId(), sharedUser);
+ mAppIds.replaceSetting(p.getAppId(), sharedUser);
}
}
}
@@ -1357,73 +1348,22 @@
mInstallerPackages.remove(packageName);
}
- /** Returns true if the requested AppID was valid and not already registered. */
- private boolean registerExistingAppIdLPw(int appId, SettingBase obj, Object name) {
- if (appId > Process.LAST_APPLICATION_UID) {
- return false;
- }
-
- if (appId >= Process.FIRST_APPLICATION_UID) {
- if (mAppIds.get(appId) != null) {
- PackageManagerService.reportSettingsProblem(Log.WARN,
- "Adding duplicate app id: " + appId
- + " name=" + name);
- return false;
- }
- mAppIds.put(appId, obj);
- } else {
- if (mOtherAppIds.get(appId) != null) {
- PackageManagerService.reportSettingsProblem(Log.WARN,
- "Adding duplicate shared id: " + appId
- + " name=" + name);
- return false;
- }
- mOtherAppIds.put(appId, obj);
- }
- return true;
- }
-
/** Gets the setting associated with the provided App ID */
public SettingBase getSettingLPr(int appId) {
- if (appId >= Process.FIRST_APPLICATION_UID) {
- return mAppIds.get(appId);
- } else {
- return mOtherAppIds.get(appId);
- }
+ return mAppIds.getSetting(appId);
}
/** Unregisters the provided app ID. */
void removeAppIdLPw(int appId) {
- if (appId >= Process.FIRST_APPLICATION_UID) {
- mAppIds.remove(appId);
- } else {
- mOtherAppIds.remove(appId);
- }
- setFirstAvailableUid(appId + 1);
+ mAppIds.removeSetting(appId);
}
-
- private void replaceAppIdLPw(int appId, SettingBase obj) {
- if (appId >= Process.FIRST_APPLICATION_UID) {
- if (appId <= mAppIds.getCurrentMaxAppId()) {
- mAppIds.put(appId, obj);
- } else {
- PackageManagerService.reportSettingsProblem(Log.WARN,
- "Error in package manager settings: calling replaceAppIdLpw to"
- + " replace SettingBase at appId=" + appId
- + " but nothing is replaced.");
- }
- } else {
- mOtherAppIds.put(appId, obj);
- }
- }
-
/**
* Transparently convert a SharedUserSetting into PackageSettings without changing appId.
* The sharedUser passed to this method has to be {@link SharedUserSetting#isSingleUser()}.
*/
void convertSharedUserSettingsLPw(SharedUserSetting sharedUser) {
final PackageSetting ps = sharedUser.getPackageSettings().valueAt(0);
- replaceAppIdLPw(sharedUser.getAppId(), ps);
+ mAppIds.replaceSetting(sharedUser.getAppId(), ps);
// Unlink the SharedUserSetting
ps.setSharedUserAppId(INVALID_UID);
@@ -4287,32 +4227,6 @@
}
}
- // This should be called (at least) whenever an application is removed
- private void setFirstAvailableUid(int uid) {
- if (uid > mFirstAvailableUid) {
- mFirstAvailableUid = uid;
- }
- }
-
- /** Returns a new AppID or -1 if we could not find an available AppID to assign */
- private int acquireAndRegisterNewAppIdLPw(SettingBase obj) {
- final int nextAvailableAppId = mAppIds.getNextAvailableAppId();
- for (int uid = mFirstAvailableUid; uid < nextAvailableAppId; uid++) {
- if (mAppIds.get(uid) == null) {
- mAppIds.put(uid, obj);
- return uid;
- }
- }
-
- // None left?
- if (nextAvailableAppId > Process.LAST_APPLICATION_UID) {
- return -1;
- }
-
- mAppIds.put(nextAvailableAppId, obj);
- return nextAvailableAppId;
- }
-
public VerifierDeviceIdentity getVerifierDeviceIdentityLPw(@NonNull Computer computer) {
if (mVerifierDeviceIdentity == null) {
mVerifierDeviceIdentity = VerifierDeviceIdentity.generate();
diff --git a/services/core/java/com/android/server/pm/ShortcutPackage.java b/services/core/java/com/android/server/pm/ShortcutPackage.java
index 8921fee..c8f809b 100644
--- a/services/core/java/com/android/server/pm/ShortcutPackage.java
+++ b/services/core/java/com/android/server/pm/ShortcutPackage.java
@@ -1827,9 +1827,9 @@
ShortcutService.writeTagExtra(out, TAG_EXTRAS, si.getExtras());
final Map<String, Map<String, List<String>>> capabilityBindings =
- si.getCapabilityBindings();
+ si.getCapabilityBindingsInternal();
if (capabilityBindings != null && !capabilityBindings.isEmpty()) {
- XmlUtils.writeMapXml(si.getCapabilityBindings(), NAME_CAPABILITY, out);
+ XmlUtils.writeMapXml(capabilityBindings, NAME_CAPABILITY, out);
}
}
diff --git a/services/core/java/com/android/server/pm/ShortcutService.java b/services/core/java/com/android/server/pm/ShortcutService.java
index 1cf2dc5..25fe000 100644
--- a/services/core/java/com/android/server/pm/ShortcutService.java
+++ b/services/core/java/com/android/server/pm/ShortcutService.java
@@ -488,7 +488,8 @@
mShortcutBitmapSaver = new ShortcutBitmapSaver(this);
mShortcutDumpFiles = new ShortcutDumpFiles(this);
mIsAppSearchEnabled = DeviceConfig.getBoolean(NAMESPACE_SYSTEMUI,
- SystemUiDeviceConfigFlags.SHORTCUT_APPSEARCH_INTEGRATION, true);
+ SystemUiDeviceConfigFlags.SHORTCUT_APPSEARCH_INTEGRATION, true)
+ && !injectIsLowRamDevice();
if (onlyForPackageManagerApis) {
return; // Don't do anything further. For unit tests only.
diff --git a/services/core/java/com/android/server/pm/StorageEventHelper.java b/services/core/java/com/android/server/pm/StorageEventHelper.java
index df19d3e..a991ed3 100644
--- a/services/core/java/com/android/server/pm/StorageEventHelper.java
+++ b/services/core/java/com/android/server/pm/StorageEventHelper.java
@@ -151,7 +151,7 @@
final AndroidPackage pkg;
try {
pkg = installPackageHelper.scanSystemPackageTracedLI(
- ps.getPath(), parseFlags, SCAN_INITIAL, 0, null);
+ ps.getPath(), parseFlags, SCAN_INITIAL, null);
loaded.add(pkg);
} catch (PackageManagerException e) {
diff --git a/services/core/java/com/android/server/pm/UserManagerService.java b/services/core/java/com/android/server/pm/UserManagerService.java
index eae7658..70053bd 100644
--- a/services/core/java/com/android/server/pm/UserManagerService.java
+++ b/services/core/java/com/android/server/pm/UserManagerService.java
@@ -4638,12 +4638,12 @@
final String restriction = getUserRemovalRestriction(userId);
if (getUserRestrictions(UserHandle.getCallingUserId()).getBoolean(restriction, false)) {
Slog.w(LOG_TAG, "Cannot remove user. " + restriction + " is enabled.");
- return UserManager.REMOVE_RESULT_ERROR;
+ return UserManager.REMOVE_RESULT_ERROR_USER_RESTRICTION;
}
}
if (userId == UserHandle.USER_SYSTEM) {
Slog.e(LOG_TAG, "System user cannot be removed.");
- return UserManager.REMOVE_RESULT_ERROR;
+ return UserManager.REMOVE_RESULT_ERROR_SYSTEM_USER;
}
final long ident = Binder.clearCallingIdentity();
@@ -4655,7 +4655,7 @@
if (userData == null) {
Slog.e(LOG_TAG,
"Cannot remove user " + userId + ", invalid user id provided.");
- return UserManager.REMOVE_RESULT_ERROR;
+ return UserManager.REMOVE_RESULT_ERROR_USER_NOT_FOUND;
}
if (mRemovingUserIds.get(userId)) {
@@ -5409,6 +5409,21 @@
(new Shell()).exec(this, in, out, err, args, callback, resultReceiver);
}
+ private static final String PREFIX_HELP_COMMAND = " ";
+ private static final String PREFIX_HELP_DESCRIPTION = " ";
+ private static final String PREFIX_HELP_DESCRIPTION_EXTRA_LINES = " ";
+
+ private static final String CMD_HELP = "help";
+ private static final String CMD_LIST = "list";
+ private static final String CMD_REPORT_SYSTEM_USER_PACKAGE_ALLOWLIST_PROBLEMS =
+ "report-system-user-package-whitelist-problems";
+
+ private static final String ARG_V = "-v";
+ private static final String ARG_VERBOSE = "--verbose";
+ private static final String ARG_ALL = "--all";
+ private static final String ARG_CRITICAL_ONLY = "--critical-only";
+ private static final String ARG_MODE = "--mode";
+
private int onShellCommand(Shell shell, String cmd) {
if (cmd == null) {
return shell.handleDefaultCommands(cmd);
@@ -5417,9 +5432,9 @@
final PrintWriter pw = shell.getOutPrintWriter();
try {
switch(cmd) {
- case "list":
+ case CMD_LIST:
return runList(pw, shell);
- case "report-system-user-package-whitelist-problems":
+ case CMD_REPORT_SYSTEM_USER_PACKAGE_ALLOWLIST_PROBLEMS:
return runReportPackageWhitelistProblems(pw, shell);
default:
return shell.handleDefaultCommands(cmd);
@@ -5436,10 +5451,10 @@
String opt;
while ((opt = shell.getNextOption()) != null) {
switch (opt) {
- case "-v":
+ case ARG_V:
verbose = true;
break;
- case "--all":
+ case ARG_ALL:
all = true;
break;
default:
@@ -5520,14 +5535,14 @@
String opt;
while ((opt = shell.getNextOption()) != null) {
switch (opt) {
- case "-v":
- case "--verbose":
+ case ARG_V:
+ case ARG_VERBOSE:
verbose = true;
break;
- case "--critical-only":
+ case ARG_CRITICAL_ONLY:
criticalOnly = true;
break;
- case "--mode":
+ case ARG_MODE:
mode = Integer.parseInt(shell.getNextArgRequired());
break;
default:
@@ -6248,20 +6263,28 @@
@Override
public void onHelp() {
final PrintWriter pw = getOutPrintWriter();
- pw.println("User manager (user) commands:");
- pw.println(" help");
- pw.println(" Prints this help text.");
- pw.println("");
- pw.println(" list [-v] [-all]");
- pw.println(" Prints all users on the system.");
- pw.println(" report-system-user-package-whitelist-problems [-v | --verbose] "
- + "[--critical-only] [--mode MODE]");
- pw.println(" Reports all issues on user-type package whitelist XML files. Options:");
- pw.println(" -v | --verbose : shows extra info, like number of issues");
- pw.println(" --critical-only: show only critical issues, excluding warnings");
- pw.println(" --mode MODE: shows what errors would be if device used mode MODE (where"
- + " MODE is the whitelist mode integer as defined by "
- + "config_userTypePackageWhitelistMode)");
+ pw.printf("User manager (user) commands:\n");
+
+ pw.printf("%s%s\n", PREFIX_HELP_COMMAND, CMD_HELP);
+ pw.printf("%sPrints this help text.\n\n", PREFIX_HELP_DESCRIPTION);
+
+ pw.printf("%s%s [%s] [%s]\n", PREFIX_HELP_COMMAND, CMD_LIST, ARG_V, ARG_ALL);
+ pw.printf("%sPrints all users on the system.\n\n", PREFIX_HELP_DESCRIPTION);
+
+ pw.printf("%s%s [%s | %s] [%s] [%s MODE]\n", PREFIX_HELP_COMMAND,
+ CMD_REPORT_SYSTEM_USER_PACKAGE_ALLOWLIST_PROBLEMS,
+ ARG_V, ARG_VERBOSE, ARG_CRITICAL_ONLY, ARG_MODE);
+
+ pw.printf("%sReports all issues on user-type package allowlist XML files. Options:\n",
+ PREFIX_HELP_DESCRIPTION);
+ pw.printf("%s%s | %s: shows extra info, like number of issues\n",
+ PREFIX_HELP_DESCRIPTION, ARG_V, ARG_VERBOSE);
+ pw.printf("%s%s: show only critical issues, excluding warnings\n",
+ PREFIX_HELP_DESCRIPTION, ARG_CRITICAL_ONLY);
+ pw.printf("%s%s MODE: shows what errors would be if device used mode MODE\n"
+ + "%s(where MODE is the allowlist mode integer as defined by "
+ + "config_userTypePackageWhitelistMode)\n\n",
+ PREFIX_HELP_DESCRIPTION, ARG_MODE, PREFIX_HELP_DESCRIPTION_EXTRA_LINES);
}
}
diff --git a/services/core/java/com/android/server/pm/permission/OneTimePermissionUserManager.java b/services/core/java/com/android/server/pm/permission/OneTimePermissionUserManager.java
index 46fde4b..6060233 100644
--- a/services/core/java/com/android/server/pm/permission/OneTimePermissionUserManager.java
+++ b/services/core/java/com/android/server/pm/permission/OneTimePermissionUserManager.java
@@ -272,6 +272,10 @@
mHandler.removeCallbacksAndMessages(mToken);
if (importance > IMPORTANCE_CACHED) {
+ if (mRevokeAfterKilledDelay == 0) {
+ onPackageInactiveLocked();
+ return;
+ }
// Delay revocation in case app is restarting
mHandler.postDelayed(() -> {
int imp = mActivityManager.getUidImportance(mUid);
diff --git a/services/core/java/com/android/server/pm/permission/PermissionManagerService.java b/services/core/java/com/android/server/pm/permission/PermissionManagerService.java
index 71554ee..5a05134b 100644
--- a/services/core/java/com/android/server/pm/permission/PermissionManagerService.java
+++ b/services/core/java/com/android/server/pm/permission/PermissionManagerService.java
@@ -562,12 +562,6 @@
}
@Override
- public void revokeOwnPermissionsOnKill(@NonNull String packageName,
- @NonNull List<String> permissions) {
- mPermissionManagerServiceImpl.revokeOwnPermissionsOnKill(packageName, permissions);
- }
-
- @Override
public boolean shouldShowRequestPermissionRationale(String packageName, String permissionName,
int userId) {
return mPermissionManagerServiceImpl.shouldShowRequestPermissionRationale(packageName,
diff --git a/services/core/java/com/android/server/pm/permission/PermissionManagerServiceImpl.java b/services/core/java/com/android/server/pm/permission/PermissionManagerServiceImpl.java
index d060930..009d155 100644
--- a/services/core/java/com/android/server/pm/permission/PermissionManagerServiceImpl.java
+++ b/services/core/java/com/android/server/pm/permission/PermissionManagerServiceImpl.java
@@ -1597,25 +1597,6 @@
}
}
- @Override
- public void revokeOwnPermissionsOnKill(String packageName, List<String> permissions) {
- final int callingUid = Binder.getCallingUid();
- int callingUserId = UserHandle.getUserId(callingUid);
- int targetPackageUid = mPackageManagerInt.getPackageUid(packageName, 0, callingUserId);
- if (targetPackageUid != callingUid) {
- throw new SecurityException("uid " + callingUid
- + " cannot revoke permissions for package " + packageName + " with uid "
- + targetPackageUid);
- }
- for (String permName : permissions) {
- if (!checkCallingOrSelfPermission(permName)) {
- throw new SecurityException("uid " + callingUid + " cannot revoke permission "
- + permName + " because it does not hold that permission");
- }
- }
- mPermissionControllerManager.revokeOwnPermissionsOnKill(packageName, permissions);
- }
-
private boolean mayManageRolePermission(int uid) {
final PackageManager packageManager = mContext.getPackageManager();
final String[] packageNames = packageManager.getPackagesForUid(uid);
diff --git a/services/core/java/com/android/server/pm/permission/PermissionManagerServiceInterface.java b/services/core/java/com/android/server/pm/permission/PermissionManagerServiceInterface.java
index 3e28320..3771f03 100644
--- a/services/core/java/com/android/server/pm/permission/PermissionManagerServiceInterface.java
+++ b/services/core/java/com/android/server/pm/permission/PermissionManagerServiceInterface.java
@@ -327,28 +327,6 @@
void revokePostNotificationPermissionWithoutKillForTest(String packageName, int userId);
/**
- * Triggers the revocation of one or more permissions for a package, under the following
- * conditions:
- * <ul>
- * <li>The package {@code packageName} must be under the same UID as the calling process
- * (typically, the target package is the calling package).
- * <li>Each permission in {@code permissions} must be granted to the package
- * {@code packageName}.
- * <li>Each permission in {@code permissions} must be a runtime permission.
- * </ul>
- * <p>
- * Background permissions which have no corresponding foreground permission still granted once
- * the revocation is effective will also be revoked.
- * <p>
- * This revocation happens asynchronously and kills all processes running in the same UID as
- * {@code packageName}. It will be triggered once it is safe to do so.
- *
- * @param packageName The name of the package for which the permissions will be revoked.
- * @param permissions List of permissions to be revoked.
- */
- void revokeOwnPermissionsOnKill(String packageName, List<String> permissions);
-
- /**
* Get whether you should show UI with rationale for requesting a permission. You should do this
* only if you do not have the permission and the context in which the permission is requested
* does not clearly communicate to the user what would be the benefit from grating this
diff --git a/services/core/java/com/android/server/pm/pkg/parsing/ParsingPackageUtils.java b/services/core/java/com/android/server/pm/pkg/parsing/ParsingPackageUtils.java
index b323948..f255db4 100644
--- a/services/core/java/com/android/server/pm/pkg/parsing/ParsingPackageUtils.java
+++ b/services/core/java/com/android/server/pm/pkg/parsing/ParsingPackageUtils.java
@@ -242,6 +242,11 @@
public static final int PARSE_CHATTY = 1 << 31;
+ /** The total maximum number of activities, services, providers and activity-aliases */
+ private static final int MAX_NUM_COMPONENTS = 30000;
+ private static final String MAX_NUM_COMPONENTS_ERR_MSG =
+ "Total number of components has exceeded the maximum number: " + MAX_NUM_COMPONENTS;
+
@IntDef(flag = true, prefix = { "PARSE_" }, value = {
PARSE_CHATTY,
PARSE_COLLECT_CERTIFICATES,
@@ -837,11 +842,20 @@
if (result.isError()) {
return input.error(result);
}
+
+ if (hasTooManyComponents(pkg)) {
+ return input.error(MAX_NUM_COMPONENTS_ERR_MSG);
+ }
}
return input.success(pkg);
}
+ private static boolean hasTooManyComponents(ParsingPackage pkg) {
+ return pkg.getActivities().size() + pkg.getServices().size() + pkg.getProviders().size()
+ > MAX_NUM_COMPONENTS;
+ }
+
/**
* For parsing non-MainComponents. Main ones have an order and some special handling which is
* done directly in {@link #parseSplitApplication(ParseInput, ParsingPackage, Resources,
@@ -2145,6 +2159,9 @@
if (result.isError()) {
return input.error(result);
}
+ if (hasTooManyComponents(pkg)) {
+ return input.error(MAX_NUM_COMPONENTS_ERR_MSG);
+ }
}
if (TextUtils.isEmpty(pkg.getStaticSharedLibName()) && TextUtils.isEmpty(
diff --git a/services/core/java/com/android/server/policy/PhoneWindowManager.java b/services/core/java/com/android/server/policy/PhoneWindowManager.java
index e79148d..dc5b325 100644
--- a/services/core/java/com/android/server/policy/PhoneWindowManager.java
+++ b/services/core/java/com/android/server/policy/PhoneWindowManager.java
@@ -792,7 +792,7 @@
public void onWakeUp() {
synchronized (mLock) {
if (shouldEnableWakeGestureLp()
- && mBatteryManagerInternal.getPlugType() != BATTERY_PLUGGED_WIRELESS) {
+ && getBatteryManagerInternal().getPlugType() != BATTERY_PLUGGED_WIRELESS) {
performHapticFeedback(HapticFeedbackConstants.VIRTUAL_KEY, false,
"Wake Up");
wakeUp(SystemClock.uptimeMillis(), mAllowTheaterModeWakeFromWakeGesture,
diff --git a/services/core/java/com/android/server/soundtrigger_middleware/AidlUtil.java b/services/core/java/com/android/server/soundtrigger_middleware/AidlUtil.java
new file mode 100644
index 0000000..f3457f5
--- /dev/null
+++ b/services/core/java/com/android/server/soundtrigger_middleware/AidlUtil.java
@@ -0,0 +1,71 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.soundtrigger_middleware;
+
+import android.media.soundtrigger.PhraseRecognitionEvent;
+import android.media.soundtrigger.PhraseRecognitionExtra;
+import android.media.soundtrigger.RecognitionEvent;
+import android.media.soundtrigger.RecognitionStatus;
+import android.media.soundtrigger.SoundModelType;
+
+/**
+ * Utilities for working with sound trigger related AIDL generated types.
+ */
+public class AidlUtil {
+ /**
+ * Initialize a new recognition event.
+ * @return The new event.
+ */
+ static RecognitionEvent newEmptyRecognitionEvent() {
+ RecognitionEvent result = new RecognitionEvent();
+ result.data = new byte[0];
+ return result;
+ }
+
+ /**
+ * Initialize a new phrase recognition event.
+ * @return The new event.
+ */
+ static PhraseRecognitionEvent newEmptyPhraseRecognitionEvent() {
+ PhraseRecognitionEvent result = new PhraseRecognitionEvent();
+ result.common = newEmptyRecognitionEvent();
+ result.phraseExtras = new PhraseRecognitionExtra[0];
+ return result;
+ }
+
+ /**
+ * Creates a new generic abort event.
+ * @return The new event.
+ */
+ static RecognitionEvent newAbortEvent() {
+ RecognitionEvent event = newEmptyRecognitionEvent();
+ event.type = SoundModelType.GENERIC;
+ event.status = RecognitionStatus.ABORTED;
+ return event;
+ }
+
+ /**
+ * Creates a new generic phrase event.
+ * @return The new event.
+ */
+ static PhraseRecognitionEvent newAbortPhraseEvent() {
+ PhraseRecognitionEvent event = newEmptyPhraseRecognitionEvent();
+ event.common.type = SoundModelType.KEYPHRASE;
+ event.common.status = RecognitionStatus.ABORTED;
+ return event;
+ }
+}
diff --git a/services/core/java/com/android/server/soundtrigger_middleware/SoundTriggerHalConcurrentCaptureHandler.java b/services/core/java/com/android/server/soundtrigger_middleware/SoundTriggerHalConcurrentCaptureHandler.java
index 990b21c..c0ab65a 100644
--- a/services/core/java/com/android/server/soundtrigger_middleware/SoundTriggerHalConcurrentCaptureHandler.java
+++ b/services/core/java/com/android/server/soundtrigger_middleware/SoundTriggerHalConcurrentCaptureHandler.java
@@ -24,7 +24,6 @@
import android.media.soundtrigger.Properties;
import android.media.soundtrigger.RecognitionConfig;
import android.media.soundtrigger.RecognitionEvent;
-import android.media.soundtrigger.RecognitionStatus;
import android.media.soundtrigger.SoundModel;
import android.media.soundtrigger.SoundModelType;
import android.media.soundtrigger.Status;
@@ -391,21 +390,14 @@
/** Notify the client that recognition has been aborted. */
private static void notifyAbort(int modelHandle, LoadedModel model) {
switch (model.type) {
- case SoundModelType.GENERIC: {
- RecognitionEvent event = new RecognitionEvent();
- event.status = RecognitionStatus.ABORTED;
- event.type = SoundModelType.GENERIC;
- model.callback.recognitionCallback(modelHandle, event);
- }
- break;
+ case SoundModelType.GENERIC:
+ model.callback.recognitionCallback(modelHandle, AidlUtil.newAbortEvent());
+ break;
- case SoundModelType.KEYPHRASE: {
- PhraseRecognitionEvent event = new PhraseRecognitionEvent();
- event.common.status = RecognitionStatus.ABORTED;
- event.common.type = SoundModelType.KEYPHRASE;
- model.callback.phraseRecognitionCallback(modelHandle, event);
- }
- break;
+ case SoundModelType.KEYPHRASE:
+ model.callback.phraseRecognitionCallback(modelHandle,
+ AidlUtil.newAbortPhraseEvent());
+ break;
}
}
diff --git a/services/core/java/com/android/server/soundtrigger_middleware/SoundTriggerModule.java b/services/core/java/com/android/server/soundtrigger_middleware/SoundTriggerModule.java
index 934b0e4..fd8dee8 100644
--- a/services/core/java/com/android/server/soundtrigger_middleware/SoundTriggerModule.java
+++ b/services/core/java/com/android/server/soundtrigger_middleware/SoundTriggerModule.java
@@ -25,6 +25,7 @@
import android.media.soundtrigger.RecognitionConfig;
import android.media.soundtrigger.RecognitionEvent;
import android.media.soundtrigger.SoundModel;
+import android.media.soundtrigger.SoundModelType;
import android.media.soundtrigger.Status;
import android.media.soundtrigger_middleware.ISoundTriggerCallback;
import android.media.soundtrigger_middleware.ISoundTriggerModule;
@@ -305,9 +306,12 @@
@Override
public void stopRecognition(int modelHandle) {
+ Model model;
synchronized (SoundTriggerModule.this) {
- mLoadedModels.get(modelHandle).stopRecognition();
+ checkValid();
+ model = mLoadedModels.get(modelHandle);
}
+ model.stopRecognition();
}
@Override
@@ -374,6 +378,7 @@
private class Model implements ISoundTriggerHal.ModelCallback {
public int mHandle;
private ModelState mState = ModelState.INIT;
+ private int mType = SoundModelType.INVALID;
private SoundTriggerMiddlewareImpl.AudioSessionProvider.AudioSession mSession;
private @NonNull
@@ -390,6 +395,7 @@
SoundTriggerMiddlewareImpl.AudioSessionProvider.AudioSession audioSession) {
mSession = audioSession;
mHandle = mHalService.loadSoundModel(model, this);
+ mType = SoundModelType.GENERIC;
setState(ModelState.LOADED);
mLoadedModels.put(mHandle, this);
return mHandle;
@@ -399,7 +405,7 @@
SoundTriggerMiddlewareImpl.AudioSessionProvider.AudioSession audioSession) {
mSession = audioSession;
mHandle = mHalService.loadPhraseSoundModel(model, this);
-
+ mType = SoundModelType.KEYPHRASE;
setState(ModelState.LOADED);
mLoadedModels.put(mHandle, this);
return mHandle;
@@ -422,12 +428,41 @@
}
private void stopRecognition() {
- if (getState() == ModelState.LOADED) {
- // This call is idempotent in order to avoid races.
- return;
+ synchronized (SoundTriggerModule.this) {
+ if (getState() == ModelState.LOADED) {
+ // This call is idempotent in order to avoid races.
+ return;
+ }
}
+ // This must be invoked outside the lock.
mHalService.stopRecognition(mHandle);
- setState(ModelState.LOADED);
+
+ // No more callbacks for this model after this point.
+ synchronized (SoundTriggerModule.this) {
+ // Generate an abortion callback to the client if the model is still active.
+ if (getState() == ModelState.ACTIVE) {
+ if (mCallback != null) {
+ try {
+ switch (mType) {
+ case SoundModelType.GENERIC:
+ mCallback.onRecognition(mHandle, AidlUtil.newAbortEvent(),
+ mSession.mSessionHandle);
+ break;
+ case SoundModelType.KEYPHRASE:
+ mCallback.onPhraseRecognition(mHandle,
+ AidlUtil.newAbortPhraseEvent(),
+ mSession.mSessionHandle);
+ break;
+ default:
+ throw new RuntimeException(
+ "Unexpected model type: " + mType);
+ }
+ } catch (RemoteException e) {
+ }
+ }
+ setState(ModelState.LOADED);
+ }
+ }
}
/** Request a forced recognition event. Will do nothing if recognition is inactive. */
@@ -518,4 +553,5 @@
}
}
}
+
}
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 2e60f13..526dccb 100644
--- a/services/core/java/com/android/server/stats/pull/StatsPullAtomService.java
+++ b/services/core/java/com/android/server/stats/pull/StatsPullAtomService.java
@@ -1633,7 +1633,14 @@
if (adapter != null) {
SynchronousResultReceiver bluetoothReceiver =
new SynchronousResultReceiver("bluetooth");
- adapter.requestControllerActivityEnergyInfo(bluetoothReceiver);
+ adapter.requestControllerActivityEnergyInfo(
+ Runnable::run,
+ info -> {
+ Bundle bundle = new Bundle();
+ bundle.putParcelable(BatteryStats.RESULT_RECEIVER_CONTROLLER_KEY, info);
+ bluetoothReceiver.send(0, bundle);
+ }
+ );
return awaitControllerInfo(bluetoothReceiver);
} else {
Slog.e(TAG, "Failed to get bluetooth adapter!");
@@ -2338,51 +2345,25 @@
}
int pullProcessDmabufMemory(int atomTag, List<StatsEvent> pulledData) {
- List<ProcessMemoryState> managedProcessList =
- LocalServices.getService(ActivityManagerInternal.class)
- .getMemoryStateForProcesses();
- for (ProcessMemoryState process : managedProcessList) {
- KernelAllocationStats.ProcessDmabuf proc =
- KernelAllocationStats.getDmabufAllocations(process.pid);
- if (proc == null || (proc.retainedBuffersCount <= 0 && proc.mappedBuffersCount <= 0)) {
- continue;
- }
- pulledData.add(
- FrameworkStatsLog.buildStatsEvent(
- atomTag,
- process.uid,
- process.processName,
- process.oomScore,
- proc.retainedSizeKb,
- proc.retainedBuffersCount,
- proc.mappedSizeKb,
- proc.mappedBuffersCount));
+ KernelAllocationStats.ProcessDmabuf[] procBufs =
+ KernelAllocationStats.getDmabufAllocations();
+
+ if (procBufs == null) {
+ return StatsManager.PULL_SKIP;
}
- SparseArray<String> processCmdlines = getProcessCmdlines();
- managedProcessList.forEach(managedProcess -> processCmdlines.delete(managedProcess.pid));
- int size = processCmdlines.size();
- for (int i = 0; i < size; ++i) {
- int pid = processCmdlines.keyAt(i);
- int uid = getUidForPid(pid);
- // ignore root processes (unlikely to be interesting)
- if (uid <= 0) {
- continue;
- }
- KernelAllocationStats.ProcessDmabuf proc =
- KernelAllocationStats.getDmabufAllocations(pid);
- if (proc == null || (proc.retainedBuffersCount <= 0 && proc.mappedBuffersCount <= 0)) {
- continue;
- }
- pulledData.add(
- FrameworkStatsLog.buildStatsEvent(
- atomTag,
- uid,
- processCmdlines.valueAt(i),
- -1001 /*Placeholder for native processes, OOM_SCORE_ADJ_MIN - 1.*/,
- proc.retainedSizeKb,
- proc.retainedBuffersCount,
- proc.mappedSizeKb,
- proc.mappedBuffersCount));
+ for (KernelAllocationStats.ProcessDmabuf procBuf : procBufs) {
+ pulledData.add(FrameworkStatsLog.buildStatsEvent(
+ atomTag,
+ procBuf.uid,
+ procBuf.processName,
+ procBuf.oomScore,
+ procBuf.retainedSizeKb,
+ procBuf.retainedBuffersCount,
+ 0, /* mapped_dmabuf_kb - deprecated */
+ 0, /* mapped_dmabuf_count - deprecated */
+ procBuf.surfaceFlingerSizeKb,
+ procBuf.surfaceFlingerCount
+ ));
}
return StatsManager.PULL_SUCCESS;
}
diff --git a/services/core/java/com/android/server/trust/TrustAgentWrapper.java b/services/core/java/com/android/server/trust/TrustAgentWrapper.java
index 20cd8f5..adca216 100644
--- a/services/core/java/com/android/server/trust/TrustAgentWrapper.java
+++ b/services/core/java/com/android/server/trust/TrustAgentWrapper.java
@@ -198,6 +198,8 @@
// Fall through.
case MSG_REVOKE_TRUST:
mTrusted = false;
+ mTrustable = false;
+ mWaitingForTrustableDowngrade = false;
mDisplayTrustGrantedMessage = false;
mMessage = null;
mHandler.removeMessages(MSG_TRUST_TIMEOUT);
diff --git a/services/core/java/com/android/server/tv/interactive/TvInteractiveAppManagerService.java b/services/core/java/com/android/server/tv/interactive/TvInteractiveAppManagerService.java
index 53a9244..672458b 100644
--- a/services/core/java/com/android/server/tv/interactive/TvInteractiveAppManagerService.java
+++ b/services/core/java/com/android/server/tv/interactive/TvInteractiveAppManagerService.java
@@ -42,8 +42,8 @@
import android.media.tv.interactive.ITvInteractiveAppServiceCallback;
import android.media.tv.interactive.ITvInteractiveAppSession;
import android.media.tv.interactive.ITvInteractiveAppSessionCallback;
-import android.media.tv.interactive.TvInteractiveAppInfo;
import android.media.tv.interactive.TvInteractiveAppService;
+import android.media.tv.interactive.TvInteractiveAppServiceInfo;
import android.net.Uri;
import android.os.Binder;
import android.os.Bundle;
@@ -130,7 +130,7 @@
new Intent(TvInteractiveAppService.SERVICE_INTERFACE),
PackageManager.GET_SERVICES | PackageManager.GET_META_DATA,
userId);
- List<TvInteractiveAppInfo> iAppList = new ArrayList<>();
+ List<TvInteractiveAppServiceInfo> iAppList = new ArrayList<>();
for (ResolveInfo ri : services) {
ServiceInfo si = ri.serviceInfo;
@@ -143,8 +143,8 @@
ComponentName component = new ComponentName(si.packageName, si.name);
try {
- TvInteractiveAppInfo info =
- new TvInteractiveAppInfo(mContext, component);
+ TvInteractiveAppServiceInfo info =
+ new TvInteractiveAppServiceInfo(mContext, component);
iAppList.add(info);
} catch (Exception e) {
Slogf.e(TAG, "failed to load TV Interactive App service " + si.name, e);
@@ -154,10 +154,10 @@
}
// sort the iApp list by iApp service id
- Collections.sort(iAppList, Comparator.comparing(TvInteractiveAppInfo::getId));
+ Collections.sort(iAppList, Comparator.comparing(TvInteractiveAppServiceInfo::getId));
Map<String, TvInteractiveAppState> iAppMap = new HashMap<>();
ArrayMap<String, Integer> tiasAppCount = new ArrayMap<>(iAppMap.size());
- for (TvInteractiveAppInfo info : iAppList) {
+ for (TvInteractiveAppServiceInfo info : iAppList) {
String iAppServiceId = info.getId();
if (DEBUG) {
Slogf.d(TAG, "add " + iAppServiceId);
@@ -195,7 +195,7 @@
for (String iAppServiceId : userState.mIAppMap.keySet()) {
if (!iAppMap.containsKey(iAppServiceId)) {
- TvInteractiveAppInfo info = userState.mIAppMap.get(iAppServiceId).mInfo;
+ TvInteractiveAppServiceInfo info = userState.mIAppMap.get(iAppServiceId).mInfo;
ServiceState serviceState = userState.mServiceStateMap.get(info.getComponent());
if (serviceState != null) {
abortPendingCreateSessionRequestsLocked(serviceState, iAppServiceId, userId);
@@ -283,7 +283,7 @@
userState.mCallbacks.finishBroadcast();
}
- private int getInteractiveAppUid(TvInteractiveAppInfo info) {
+ private int getInteractiveAppUid(TvInteractiveAppServiceInfo info) {
try {
return getContext().getPackageManager().getApplicationInfo(
info.getServiceInfo().packageName, 0).uid;
@@ -642,7 +642,7 @@
private final class BinderService extends ITvInteractiveAppManager.Stub {
@Override
- public List<TvInteractiveAppInfo> getTvInteractiveAppServiceList(int userId) {
+ public List<TvInteractiveAppServiceInfo> getTvInteractiveAppServiceList(int userId) {
final int resolvedUserId = resolveCallingUserId(Binder.getCallingPid(),
Binder.getCallingUid(), userId, "getTvInteractiveAppServiceList");
final long identity = Binder.clearCallingIdentity();
@@ -653,7 +653,7 @@
mGetServiceListCalled = true;
}
UserState userState = getOrCreateUserStateLocked(resolvedUserId);
- List<TvInteractiveAppInfo> iAppList = new ArrayList<>();
+ List<TvInteractiveAppServiceInfo> iAppList = new ArrayList<>();
for (TvInteractiveAppState state : userState.mIAppMap.values()) {
iAppList.add(state.mInfo);
}
@@ -665,42 +665,6 @@
}
@Override
- public void prepare(String tiasId, int type, int userId) {
- // TODO: bind service
- final int resolvedUserId = resolveCallingUserId(Binder.getCallingPid(),
- Binder.getCallingUid(), userId, "prepare");
- final long identity = Binder.clearCallingIdentity();
- try {
- synchronized (mLock) {
- UserState userState = getOrCreateUserStateLocked(resolvedUserId);
- TvInteractiveAppState iAppState = userState.mIAppMap.get(tiasId);
- if (iAppState == null) {
- Slogf.e(TAG, "failed to prepare TIAS - unknown TIAS id " + tiasId);
- return;
- }
- ComponentName componentName = iAppState.mInfo.getComponent();
- ServiceState serviceState = userState.mServiceStateMap.get(componentName);
- if (serviceState == null) {
- serviceState = new ServiceState(
- componentName, tiasId, resolvedUserId, true, type);
- userState.mServiceStateMap.put(componentName, serviceState);
- updateServiceConnectionLocked(componentName, resolvedUserId);
- } else if (serviceState.mService != null) {
- serviceState.mService.prepare(type);
- } else {
- serviceState.mPendingPrepare = true;
- serviceState.mPendingPrepareType = type;
- updateServiceConnectionLocked(componentName, resolvedUserId);
- }
- }
- } catch (RemoteException e) {
- Slogf.e(TAG, "error in prepare", e);
- } finally {
- Binder.restoreCallingIdentity(identity);
- }
- }
-
- @Override
public void registerAppLinkInfo(String tiasId, AppLinkInfo appLinkInfo, int userId) {
final int resolvedUserId = resolveCallingUserId(Binder.getCallingPid(),
Binder.getCallingUid(), userId, "registerAppLinkInfo: " + appLinkInfo);
@@ -1360,6 +1324,32 @@
}
@Override
+ public void sendSigningResult(
+ IBinder sessionToken, String signingId, byte[] result, int userId) {
+ if (DEBUG) {
+ Slogf.d(TAG, "sendSigningResult(signingId=%s)", signingId);
+ }
+ final int callingUid = Binder.getCallingUid();
+ final int resolvedUserId = resolveCallingUserId(Binder.getCallingPid(), callingUid,
+ userId, "sendSigningResult");
+ SessionState sessionState = null;
+ final long identity = Binder.clearCallingIdentity();
+ try {
+ synchronized (mLock) {
+ try {
+ sessionState = getSessionStateLocked(sessionToken, callingUid,
+ resolvedUserId);
+ getSessionLocked(sessionState).sendSigningResult(signingId, result);
+ } catch (RemoteException | SessionNotFoundException e) {
+ Slogf.e(TAG, "error in sendSigningResult", e);
+ }
+ }
+ } finally {
+ Binder.restoreCallingIdentity(identity);
+ }
+ }
+
+ @Override
public void setSurface(IBinder sessionToken, Surface surface, int userId) {
final int callingUid = Binder.getCallingUid();
final int resolvedUserId = resolveCallingUserId(Binder.getCallingPid(), callingUid,
@@ -1679,7 +1669,6 @@
}
boolean shouldBind = (!serviceState.mSessionTokens.isEmpty())
- || (serviceState.mPendingPrepare)
|| (!serviceState.mPendingAppLinkInfo.isEmpty())
|| (!serviceState.mPendingAppLinkCommand.isEmpty());
@@ -1738,7 +1727,7 @@
private static final class TvInteractiveAppState {
private String mIAppServiceId;
private ComponentName mComponentName;
- private TvInteractiveAppInfo mInfo;
+ private TvInteractiveAppServiceInfo mInfo;
private int mUid;
private int mIAppNumber;
}
@@ -1831,22 +1820,13 @@
private final List<Pair<AppLinkInfo, Boolean>> mPendingAppLinkInfo = new ArrayList<>();
private final List<Bundle> mPendingAppLinkCommand = new ArrayList<>();
- private boolean mPendingPrepare = false;
- private Integer mPendingPrepareType = null;
private ITvInteractiveAppService mService;
private ServiceCallback mCallback;
private boolean mBound;
private boolean mReconnecting;
private ServiceState(ComponentName component, String tias, int userId) {
- this(component, tias, userId, false, null);
- }
-
- private ServiceState(ComponentName component, String tias, int userId,
- boolean pendingPrepare, Integer prepareType) {
mComponent = component;
- mPendingPrepare = pendingPrepare;
- mPendingPrepareType = prepareType;
mConnection = new InteractiveAppServiceConnection(component, userId);
mIAppServiceId = tias;
}
@@ -1894,19 +1874,6 @@
}
}
- if (serviceState.mPendingPrepare) {
- final long identity = Binder.clearCallingIdentity();
- try {
- serviceState.mService.prepare(serviceState.mPendingPrepareType);
- serviceState.mPendingPrepare = false;
- serviceState.mPendingPrepareType = null;
- } catch (RemoteException e) {
- Slogf.e(TAG, "error in prepare when onServiceConnected", e);
- } finally {
- Binder.restoreCallingIdentity(identity);
- }
- }
-
if (!serviceState.mPendingAppLinkInfo.isEmpty()) {
for (Iterator<Pair<AppLinkInfo, Boolean>> it =
serviceState.mPendingAppLinkInfo.iterator();
@@ -2221,6 +2188,24 @@
}
@Override
+ public void onRequestSigning(String id, String algorithm, String alias, byte[] data) {
+ synchronized (mLock) {
+ if (DEBUG) {
+ Slogf.d(TAG, "onRequestSigning");
+ }
+ if (mSessionState.mSession == null || mSessionState.mClient == null) {
+ return;
+ }
+ try {
+ mSessionState.mClient.onRequestSigning(
+ id, algorithm, alias, data, mSessionState.mSeq);
+ } catch (RemoteException e) {
+ Slogf.e(TAG, "error in onRequestSigning", e);
+ }
+ }
+ }
+
+ @Override
public void onAdRequest(AdRequest request) {
synchronized (mLock) {
if (DEBUG) {
diff --git a/services/core/java/com/android/server/utils/TimingsTraceAndSlog.java b/services/core/java/com/android/server/utils/TimingsTraceAndSlog.java
index 397acfa..b45c962 100644
--- a/services/core/java/com/android/server/utils/TimingsTraceAndSlog.java
+++ b/services/core/java/com/android/server/utils/TimingsTraceAndSlog.java
@@ -88,7 +88,7 @@
@Override
public void traceBegin(@NonNull String name) {
- Slog.i(mTag, name);
+ Slog.d(mTag, name);
super.traceBegin(name);
}
diff --git a/services/core/java/com/android/server/wm/AccessibilityWindowsPopulator.java b/services/core/java/com/android/server/wm/AccessibilityWindowsPopulator.java
index d4648a4..11ddac6 100644
--- a/services/core/java/com/android/server/wm/AccessibilityWindowsPopulator.java
+++ b/services/core/java/com/android/server/wm/AccessibilityWindowsPopulator.java
@@ -30,6 +30,7 @@
import android.os.InputConfig;
import android.os.Looper;
import android.os.Message;
+import android.util.Pair;
import android.util.Slog;
import android.util.SparseArray;
import android.view.IWindow;
@@ -94,8 +95,6 @@
mService = service;
mAccessibilityController = accessibilityController;
mHandler = new MyHandler(mService.mH.getLooper());
-
- register();
}
/**
@@ -219,8 +218,10 @@
}
mWindowsNotificationEnabled = register;
if (mWindowsNotificationEnabled) {
- populateVisibleWindowHandlesAndNotifyWindowsChangeIfNeeded();
+ Pair<InputWindowHandle[], DisplayInfo[]> info = register();
+ onWindowInfosChangedInternal(info.first, info.second);
} else {
+ unregister();
releaseResources();
}
}
diff --git a/services/core/java/com/android/server/wm/ActivityClientController.java b/services/core/java/com/android/server/wm/ActivityClientController.java
index 543e44c..ffc4388 100644
--- a/services/core/java/com/android/server/wm/ActivityClientController.java
+++ b/services/core/java/com/android/server/wm/ActivityClientController.java
@@ -746,8 +746,9 @@
// if it is not already expanding to fullscreen. Otherwise, the arguments will
// be used the next time the activity enters PiP.
final Task rootTask = r.getRootTask();
- rootTask.setPictureInPictureAspectRatio(r.pictureInPictureArgs.getAspectRatio(),
- r.pictureInPictureArgs.getExpandedAspectRatio());
+ rootTask.setPictureInPictureAspectRatio(
+ r.pictureInPictureArgs.getAspectRatioFloat(),
+ r.pictureInPictureArgs.getExpandedAspectRatioFloat());
rootTask.setPictureInPictureActions(r.pictureInPictureArgs.getActions());
}
}
@@ -828,7 +829,7 @@
if (params.hasSetAspectRatio()
&& !mService.mWindowManager.isValidPictureInPictureAspectRatio(
- r.mDisplayContent, params.getAspectRatio())) {
+ r.mDisplayContent, params.getAspectRatioFloat())) {
throw new IllegalArgumentException(String.format(caller
+ ": Aspect ratio is too extreme (must be between %f and %f).",
minAspectRatio, maxAspectRatio));
@@ -836,7 +837,7 @@
if (mService.mSupportsExpandedPictureInPicture && params.hasSetExpandedAspectRatio()
&& !mService.mWindowManager.isValidExpandedPictureInPictureAspectRatio(
- r.mDisplayContent, params.getExpandedAspectRatio())) {
+ r.mDisplayContent, params.getExpandedAspectRatioFloat())) {
throw new IllegalArgumentException(String.format(caller
+ ": Expanded aspect ratio is not extreme enough (must not be between"
+ " %f and %f).",
diff --git a/services/core/java/com/android/server/wm/ActivityMetricsLogger.java b/services/core/java/com/android/server/wm/ActivityMetricsLogger.java
index a8dd856..7f84f61 100644
--- a/services/core/java/com/android/server/wm/ActivityMetricsLogger.java
+++ b/services/core/java/com/android/server/wm/ActivityMetricsLogger.java
@@ -191,6 +191,35 @@
private long mCurrentTransitionStartTimeNs;
/** Non-null when a {@link TransitionInfo} is created for this state. */
private TransitionInfo mAssociatedTransitionInfo;
+ /** The sequence id for trace. It is used to map the traces before resolving intent. */
+ private static int sTraceSeqId;
+ /** The trace format is "launchingActivity#$seqId:$state(:$packageName)". */
+ final String mTraceName;
+
+ LaunchingState() {
+ if (!Trace.isTagEnabled(Trace.TRACE_TAG_ACTIVITY_MANAGER)) {
+ mTraceName = null;
+ return;
+ }
+ // Use an id because the launching app is not yet known before resolving intent.
+ sTraceSeqId++;
+ mTraceName = "launchingActivity#" + sTraceSeqId;
+ Trace.asyncTraceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, mTraceName, 0);
+ }
+
+ void stopTrace(boolean abort) {
+ if (mTraceName == null) return;
+ Trace.asyncTraceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER, mTraceName, 0);
+ final String launchResult;
+ if (mAssociatedTransitionInfo == null) {
+ launchResult = ":failed";
+ } else {
+ launchResult = (abort ? ":canceled:" : ":completed:")
+ + mAssociatedTransitionInfo.mLastLaunchedActivity.packageName;
+ }
+ // Put a supplement trace as the description of the async trace with the same id.
+ Trace.instant(Trace.TRACE_TAG_ACTIVITY_MANAGER, mTraceName + launchResult);
+ }
@VisibleForTesting
boolean allDrawn() {
@@ -549,10 +578,10 @@
}
if (existingInfo == null) {
- // Only notify the observer for a new launching event.
- launchObserverNotifyIntentStarted(intent, transitionStartTimeNs);
final LaunchingState launchingState = new LaunchingState();
launchingState.mCurrentTransitionStartTimeNs = transitionStartTimeNs;
+ // Only notify the observer for a new launching event.
+ launchObserverNotifyIntentStarted(intent, transitionStartTimeNs);
return launchingState;
}
existingInfo.mLaunchingState.mCurrentTransitionStartTimeNs = transitionStartTimeNs;
@@ -574,7 +603,7 @@
@Nullable ActivityOptions options) {
if (launchedActivity == null) {
// The launch is aborted, e.g. intent not resolved, class not found.
- abort(null /* info */, "nothing launched");
+ abort(launchingState, "nothing launched");
return;
}
@@ -601,7 +630,7 @@
if (launchedActivity.isReportedDrawn() && launchedActivity.isVisible()) {
// Launched activity is already visible. We cannot measure windows drawn delay.
- abort(info, "launched activity already visible");
+ abort(launchingState, "launched activity already visible");
return;
}
@@ -633,7 +662,7 @@
final TransitionInfo newInfo = TransitionInfo.create(launchedActivity, launchingState,
options, processRunning, processSwitch, newActivityCreated, resultCode);
if (newInfo == null) {
- abort(info, "unrecognized launch");
+ abort(launchingState, "unrecognized launch");
return;
}
@@ -657,7 +686,7 @@
for (int i = mTransitionInfoList.size() - 2; i >= 0; i--) {
final TransitionInfo prevInfo = mTransitionInfoList.get(i);
if (prevInfo.mIsDrawn || !prevInfo.mLastLaunchedActivity.mVisibleRequested) {
- abort(prevInfo, "nothing will be drawn");
+ scheduleCheckActivityToBeDrawn(prevInfo.mLastLaunchedActivity, 0 /* delay */);
}
}
}
@@ -757,6 +786,10 @@
/** Makes sure that the reference to the removed activity is cleared. */
void notifyActivityRemoved(@NonNull ActivityRecord r) {
mLastTransitionInfo.remove(r);
+ final TransitionInfo info = getActiveTransitionInfo(r);
+ if (info != null) {
+ abort(info, "removed");
+ }
final int packageUid = r.info.applicationInfo.uid;
final PackageCompatStateInfo compatStateInfo = mPackageUidToCompatStateInfo.get(packageUid);
@@ -870,23 +903,29 @@
}
}
+ private void abort(@NonNull LaunchingState state, String cause) {
+ if (state.mAssociatedTransitionInfo != null) {
+ abort(state.mAssociatedTransitionInfo, cause);
+ return;
+ }
+ if (DEBUG_METRICS) Slog.i(TAG, "abort launch cause=" + cause);
+ state.stopTrace(true /* abort */);
+ launchObserverNotifyIntentFailed();
+ }
+
/** Aborts tracking of current launch metrics. */
- private void abort(TransitionInfo info, String cause) {
+ private void abort(@NonNull TransitionInfo info, String cause) {
done(true /* abort */, info, cause, 0L /* timestampNs */);
}
/** Called when the given transition (info) is no longer active. */
- private void done(boolean abort, @Nullable TransitionInfo info, String cause,
+ private void done(boolean abort, @NonNull TransitionInfo info, String cause,
long timestampNs) {
if (DEBUG_METRICS) {
Slog.i(TAG, "done abort=" + abort + " cause=" + cause + " timestamp=" + timestampNs
+ " info=" + info);
}
- if (info == null) {
- launchObserverNotifyIntentFailed();
- return;
- }
-
+ info.mLaunchingState.stopTrace(abort);
stopLaunchTrace(info);
final Boolean isHibernating =
mLastHibernationStates.remove(info.mLastLaunchedActivity.packageName);
@@ -1453,7 +1492,7 @@
/** Starts trace for an activity is actually launching. */
private void startLaunchTrace(@NonNull TransitionInfo info) {
if (DEBUG_METRICS) Slog.i(TAG, "startLaunchTrace " + info);
- if (!Trace.isTagEnabled(Trace.TRACE_TAG_ACTIVITY_MANAGER)) {
+ if (info.mLaunchingState.mTraceName == null) {
return;
}
info.mLaunchTraceName = "launching: " + info.mLastLaunchedActivity.packageName;
diff --git a/services/core/java/com/android/server/wm/ActivityRecord.java b/services/core/java/com/android/server/wm/ActivityRecord.java
index 883ce99..67b846b 100644
--- a/services/core/java/com/android/server/wm/ActivityRecord.java
+++ b/services/core/java/com/android/server/wm/ActivityRecord.java
@@ -550,7 +550,7 @@
private void updateEnterpriseThumbnailDrawable(Context context) {
DevicePolicyManager dpm = context.getSystemService(DevicePolicyManager.class);
- mEnterpriseThumbnailDrawable = dpm.getDrawable(
+ mEnterpriseThumbnailDrawable = dpm.getResources().getDrawable(
WORK_PROFILE_ICON, OUTLINE, PROFILE_SWITCH_ANIMATION,
() -> context.getDrawable(R.drawable.ic_corp_badge));
}
@@ -5603,19 +5603,8 @@
"makeInvisible", true /* beforeStopping */);
// Defer telling the client it is hidden if it can enter Pip and isn't current paused,
// stopped or stopping. This gives it a chance to enter Pip in onPause().
- // TODO: There is still a question surrounding activities in multi-window mode that want
- // to enter Pip after they are paused, but are still visible. I they should be okay to
- // enter Pip in those cases, but not "auto-Pip" which is what this condition covers and
- // the current contract for "auto-Pip" is that the app should enter it before onPause
- // returns. Just need to confirm this reasoning makes sense.
final boolean deferHidingClient = canEnterPictureInPicture
&& !isState(STARTED, STOPPING, STOPPED, PAUSED);
- if (!mTransitionController.isShellTransitionsEnabled()
- && deferHidingClient && pictureInPictureArgs.isAutoEnterEnabled()) {
- // Go ahead and just put the activity in pip if it supports auto-pip.
- mAtmService.enterPictureInPictureMode(this, pictureInPictureArgs);
- return;
- }
setDeferHidingClient(deferHidingClient);
setVisibility(false);
diff --git a/services/core/java/com/android/server/wm/ActivityStarter.java b/services/core/java/com/android/server/wm/ActivityStarter.java
index 7d2dfa0..77ec67f 100644
--- a/services/core/java/com/android/server/wm/ActivityStarter.java
+++ b/services/core/java/com/android/server/wm/ActivityStarter.java
@@ -2730,10 +2730,11 @@
false /* includingParents */);
intentTask = intentTask.getParent().asTaskFragment().getTask();
}
- // If the task is in multi-windowing mode, the activity may already be on
+ // If the activity is visible in multi-windowing mode, it may already be on
// the top (visible to user but not the global top), then the result code
// should be START_DELIVERED_TO_TOP instead of START_TASK_TO_FRONT.
final boolean wasTopOfVisibleRootTask = intentActivity.mVisibleRequested
+ && intentActivity.inMultiWindowMode()
&& intentActivity == mTargetRootTask.topRunningActivity();
// We only want to move to the front, if we aren't going to launch on a
// different root task. If we launch on a different root task, we will put the
diff --git a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
index b5312c4..988a7c6 100644
--- a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
+++ b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
@@ -3523,8 +3523,9 @@
}
// Only update the saved args from the args that are set
r.setPictureInPictureParams(params);
- final float aspectRatio = r.pictureInPictureArgs.getAspectRatio();
- final float expandedAspectRatio = r.pictureInPictureArgs.getExpandedAspectRatio();
+ final float aspectRatio = r.pictureInPictureArgs.getAspectRatioFloat();
+ final float expandedAspectRatio =
+ r.pictureInPictureArgs.getExpandedAspectRatioFloat();
final List<RemoteAction> actions = r.pictureInPictureArgs.getActions();
mRootWindowContainer.moveActivityToPinnedRootTask(r,
null /* launchIntoPipHostActivity */, "enterPictureInPictureMode");
diff --git a/services/core/java/com/android/server/wm/BLASTSync.md b/services/core/java/com/android/server/wm/BLASTSync.md
new file mode 100644
index 0000000..2f39d6d
--- /dev/null
+++ b/services/core/java/com/android/server/wm/BLASTSync.md
@@ -0,0 +1,108 @@
+= What does it mean for BLAST Sync to work? =
+There are two BLAST sync primitives on the server side, BLASTSyncEngine and applyWithNextDraw.
+Both of them are used to solve subclasses of this category of problem:
+ 1. You have some server side changes, which will trigger both WM/SysUI initiated SurfaceControl.Transactions,
+ and also trigger a client redraw/update
+ 2. You want to synchronize the redraw of those clients with the application of those WM/SysUI side changes.
+
+Put simply, you would like to synchronize the graphical effects of some WM changes with the graphical output of various windows
+observing those changes.
+
+To talk about exactly what the primitives guarantee, we need to clarify what we mean by server side changes.
+In this document we will use a term syncable state to refer to any state mutated under the WindowManager lock
+which when observed by the client, produces a visible outcome in the produced frame.
+For example the current Configuration.
+
+The guarantee provided by Server-side BLAST Sync Primitives is thus:
+Guarantee 1: If you make a set of changes to syncable state, at the same time that you begin a sync,
+then the first frame drawn by the client after observing the syncable state will be sent in a transaction
+to the consumer of the sync which was begun, rather than directly sent to SurfaceFlinger.
+
+Here "at the same time" means in the same critical section (while holding the WM lock)
+For example this guarantee means that you can write code like:
+ window.performConfigurationChange(someConfiguration)
+ window.applyOnNextDraw(consumer)
+And the consumer will always be passed the first frame containing the configuration change. This can work with any
+syncable state not just Configuration.
+
+The following is the protocol and additional requirements for BLAST sync, and an analysis of why it is correct. Due to time
+constraints we analyze it for a single window only (as this is actually the hard part).
+
+Protocol requirements:
+ Server protocol, precondition, begin a syncSeqId integer per window at 0:
+ SA: Enter the critical section
+ SB: Change syncable state, any number of times, prepare any number of syncs (and
+ increment the seqId if a sync was prepared, assosciate it with the sync)
+ SC: Leave the critical section
+ SD: Send syncable state updates to the client, always paired with the current seqId
+ SE: When the client calls finishDrawing, execute the consumer for each sync with
+ seqId <= the seqId which the client passed to finishDrawing
+ Client protocol:
+ CA: Observe state and seqid changes up until a fixed frame deadline, then execute performTraversals
+ CB: If the seqId is incremeneted at the time of the frame deadline, configure the renderer to
+ redirect the next draw in to a transaction, record the seqId at the time
+ CC: When the draw is finished, send the transaction containing the draw to WM with the
+ previously recorded seqId
+ Additional requirements/assumptions:
+ 1. The server may only send changes to the syncable state paired with the seqId. The client may
+ only receive them together (e.g. not from other sources)
+ 2. In between changing and sending syncable state, the lock must be released and acquired again
+ 3. The client wont draw a frame reflecting syncable state changes without passing through "performTraversals"
+ 4. Drawing never fails
+ 5. There are no blocking calls between the client or the server
+
+Note that the server can begin the protocol at any time, so it may be possible for the client to proceed through
+phases SA, SB, SC, and SD multiple times before the client receives any messages.
+
+To show that the guarantee can't be violated, we use a notation of sequences, where we describe interleaving
+of protocol events. For duplicate events, we attach a number, e.g. SA_1, SA_2.
+
+We proceed by contradiction, imagine there was some sequence (..., SA_N, ...) for which the guarantee was
+not upheld. This means that either
+ 1. finishDrawing with the assosciate seqId was never sent to the server OR
+ 2. It was sent too late (after the first frame was sent to SF instead of WM) OR
+ 3. It was sent too early (not containing the state changes originating with SA_N)
+If it was sent neither too late, nor too early, and contained the assosciated seqId, then protocol step SE
+says that the frame will be passed to the consumer and we uphold our guarantee.
+
+The first case is impossible because step SD says that the server always sends the seqId if a sync was prepared.
+If we send it the client must receive it. Since we only increment the seqId, and the client only takes the
+seqId from us (requirement 1, protocol step SB), the received ID must be higher than the clients previous seqId.
+CA says that performTraversals will execute, and CB says that when it does, if the seqId is higher than before
+it will schedule the render to sync. Requirement 4 says drawing never fails, so CC must execute, and so we will always
+eventually send every seqId (or a seqId > than it) back to the server.
+
+It also can't be sent too late. By requirement 2 we must release and acquire the lock
+after after changing and before emitting syncable state changes. This means it's guaranteed
+that even in an ordering like AcquireLock, ChangeState, PrepareSync, Release lock we can't
+send the state changes before prepareSync, and so they can always include at least the seqId
+assosciated with changestate (or a later one).
+Since we only receive the SeqId with the State changes (requirement 1),
+and we wont draw state changes without passing through perform traversals (requirement 3) the first frame
+containing the state change must have been generated by a call to performTraversals which also observed
+the seqId change, and so it will appropriately configure the renderer.
+
+By the same argument it can't be sent too early! Since we only send seqIds we receive from the server,
+and we only send seqIds after completing a drawing pass of the assosciated state.
+
+So we can see that no matter at what time the server makes syncable state changes, the first frame will
+always be delivered to the draw handler. Assuming that the client and server uphold this protocol and these
+requirements.
+
+The trickiest part of the implementation at the moment is due to assosciating seqId. Currently we send one of the most
+most important pieces of syncable state (configuration) over multiple channels. Namely ClientTransaction
+and MSG_RESIZED. The ordering of these relative to sync preparation in server code is undefined, in fact we have cases like
+this all the time:
+ acquireLock()
+ changeConfiguration()
+ // time passes, but still in critical section
+ prepareSync()
+ releaseLock()
+This is exactly the kind of case Guarantee 1 mentions as an example. In previous incarnations of the code this worked
+because relayoutWindow needed to acquire the same lock and relayoutWindow was a necessary part of completing sync.
+
+Now that we have no barrier, that could create issues, because at the time we change configuration (and send the change
+to the client via ClientTransaction), we haven't even incremented the seqId yet, and so how can the client observe it
+at the same time as the state? We solve this by pushing all client communication through a handler thread that has to
+acquire the lock. This ensures we uphold requirement 2.
+
diff --git a/services/core/java/com/android/server/wm/BackNavigationController.java b/services/core/java/com/android/server/wm/BackNavigationController.java
index 23f14a7..dbc0141 100644
--- a/services/core/java/com/android/server/wm/BackNavigationController.java
+++ b/services/core/java/com/android/server/wm/BackNavigationController.java
@@ -25,6 +25,7 @@
import android.graphics.Point;
import android.graphics.Rect;
import android.hardware.HardwareBuffer;
+import android.os.Bundle;
import android.os.RemoteCallback;
import android.os.RemoteException;
import android.os.SystemProperties;
@@ -44,7 +45,11 @@
class BackNavigationController {
private static final String TAG = "BackNavigationController";
- private static final String BACK_PREDICTABILITY_PROP = "persist.debug.back_predictability";
+ // By default, enable new back dispatching without any animations.
+ private static final int BACK_PREDICTABILITY_PROP =
+ SystemProperties.getInt("persist.debug.back_predictability", 1);
+ private static final int ANIMATIONS_MASK = 1 << 1;
+ private static final int SCREENSHOT_MASK = 1 << 2;
@Nullable
private TaskSnapshotController mTaskSnapshotController;
@@ -53,11 +58,15 @@
* Returns true if the back predictability feature is enabled
*/
static boolean isEnabled() {
- return SystemProperties.getInt(BACK_PREDICTABILITY_PROP, 0) > 0;
+ return BACK_PREDICTABILITY_PROP > 0;
}
static boolean isScreenshotEnabled() {
- return false;
+ return (BACK_PREDICTABILITY_PROP & SCREENSHOT_MASK) != 0;
+ }
+
+ private static boolean isAnimationEnabled() {
+ return (BACK_PREDICTABILITY_PROP & ANIMATIONS_MASK) != 0;
}
/**
@@ -93,14 +102,17 @@
ActivityRecord prev;
WindowContainer<?> removedWindowContainer;
ActivityRecord activityRecord;
+ ActivityRecord prevTaskTopActivity = null;
SurfaceControl animationLeashParent;
WindowConfiguration taskWindowConfiguration;
HardwareBuffer screenshotBuffer = null;
+ SurfaceControl screenshotSurface;
int prevTaskId;
int prevUserId;
RemoteAnimationTarget topAppTarget;
SurfaceControl animLeash;
- IOnBackInvokedCallback callback = null;
+ IOnBackInvokedCallback applicationCallback = null;
+ IOnBackInvokedCallback systemCallback = null;
synchronized (task.mWmService.mGlobalLock) {
@@ -116,15 +128,14 @@
removedWindowContainer = activityRecord;
taskWindowConfiguration = window.getWindowConfiguration();
}
- IOnBackInvokedCallback applicationCallback = null;
- IOnBackInvokedCallback systemCallback = null;
if (window != null) {
applicationCallback = window.getApplicationOnBackInvokedCallback();
- callback = applicationCallback;
- if (callback == null) {
- systemCallback = window.getSystemOnBackInvokedCallback();
- callback = systemCallback;
- }
+ systemCallback = window.getSystemOnBackInvokedCallback();
+ }
+ if (applicationCallback == null && systemCallback == null) {
+ // Return null when either there's no window, or apps have just initialized and
+ // have not finished registering callbacks.
+ return null;
}
ProtoLog.d(WM_DEBUG_BACK_PREVIEW, "startBackNavigation task=%s, "
@@ -133,24 +144,24 @@
task, activityRecord, applicationCallback, systemCallback);
// TODO Temp workaround for Sysui until b/221071505 is fixed
- if (activityRecord == null && callback != null) {
+ if (activityRecord == null && applicationCallback != null) {
return new BackNavigationInfo(BackNavigationInfo.TYPE_CALLBACK,
null /* topWindowLeash */, null /* screenshotSurface */,
null /* screenshotBuffer */, null /* taskWindowConfiguration */,
null /* onBackNavigationDone */,
- callback /* onBackInvokedCallback */);
+ applicationCallback /* onBackInvokedCallback */);
}
// For IME and Home, either a callback is registered, or we do nothing. In both cases,
// we don't need to pass the leashes below.
if (activityRecord == null || task.getDisplayContent().getImeContainer().isVisible()
|| activityRecord.isActivityTypeHome()) {
- if (callback != null) {
+ if (applicationCallback != null) {
return new BackNavigationInfo(BackNavigationInfo.TYPE_CALLBACK,
null /* topWindowLeash */, null /* screenshotSurface */,
null /* screenshotBuffer */, null /* taskWindowConfiguration */,
null /* onBackNavigationDone */,
- callback /* onBackInvokedCallback */);
+ applicationCallback /* onBackInvokedCallback */);
} else {
return null;
}
@@ -159,12 +170,12 @@
prev = task.getActivity(
(r) -> !r.finishing && r.getTask() == task && !r.isTopRunningActivity());
- if (callback != null) {
+ if (applicationCallback != null) {
return new BackNavigationInfo(BackNavigationInfo.TYPE_CALLBACK,
null /* topWindowLeash */, null /* screenshotSurface */,
null /* screenshotBuffer */, null /* taskWindowConfiguration */,
null /* onBackNavigationDone */,
- callback /* onBackInvokedCallback */);
+ applicationCallback /* onBackInvokedCallback */);
} else if (prev != null) {
backType = BackNavigationInfo.TYPE_CROSS_ACTIVITY;
} else if (task.returnsToHomeRootTask()) {
@@ -188,8 +199,8 @@
prevTaskId = prevTask != null ? prevTask.mTaskId : 0;
prevUserId = prevTask != null ? prevTask.mUserId : 0;
- ProtoLog.d(WM_DEBUG_BACK_PREVIEW, "Previous Activity is %s",
- prev != null ? prev.mActivityComponent : null);
+ ProtoLog.d(WM_DEBUG_BACK_PREVIEW, "Previous Activity is %s. "
+ + "Back type is %s", prev != null ? prev.mActivityComponent : null, backType);
//TODO(207481538) Remove once the infrastructure to support per-activity screenshot is
// implemented. For now we simply have the mBackScreenshots hash map that dumbly
@@ -204,6 +215,7 @@
return null;
}
// Prepare a leash to animate the current top window
+ // TODO(b/220934562): Use surface animator to better manage animation conflicts.
animLeash = removedWindowContainer.makeAnimationLeash()
.setName("BackPreview Leash for " + removedWindowContainer)
.setHidden(false)
@@ -231,12 +243,30 @@
activityRecord.windowType);
}
- SurfaceControl.Builder builder = new SurfaceControl.Builder()
+ screenshotSurface = new SurfaceControl.Builder()
.setName("BackPreview Screenshot for " + prev)
.setParent(animationLeashParent)
.setHidden(false)
- .setBLASTLayer();
- SurfaceControl screenshotSurface = builder.build();
+ .setBLASTLayer()
+ .build();
+ if (backType == BackNavigationInfo.TYPE_RETURN_TO_HOME && isAnimationEnabled()) {
+ task.mBackGestureStarted = true;
+ // Make launcher show from behind by marking its top activity as visible and
+ // launch-behind to bump its visibility for the duration of the back gesture.
+ prevTaskTopActivity = prevTask.getTopNonFinishingActivity();
+ if (prevTaskTopActivity != null) {
+ if (!prevTaskTopActivity.mVisibleRequested) {
+ prevTaskTopActivity.setVisibility(true);
+ }
+ prevTaskTopActivity.mLaunchTaskBehind = true;
+ ProtoLog.d(WM_DEBUG_BACK_PREVIEW,
+ "Setting Activity.mLauncherTaskBehind to true. Activity=%s",
+ prevTaskTopActivity);
+ prevTaskTopActivity.mRootWindowContainer.ensureActivitiesVisible(
+ null /* starting */, 0 /* configChanges */,
+ false /* preserveWindows */);
+ }
+ }
// Find a screenshot of the previous activity
@@ -253,17 +283,20 @@
WindowContainer<?> finalRemovedWindowContainer = removedWindowContainer;
try {
- activityRecord.token.linkToDeath(
- () -> resetSurfaces(finalRemovedWindowContainer), 0);
+ activityRecord.token.linkToDeath(() -> resetSurfaces(finalRemovedWindowContainer), 0);
} catch (RemoteException e) {
Slog.e(TAG, "Failed to link to death", e);
resetSurfaces(removedWindowContainer);
return null;
}
- RemoteCallback onBackNavigationDone = new RemoteCallback(
- result -> resetSurfaces(finalRemovedWindowContainer
- ));
+ int finalBackType = backType;
+ final IOnBackInvokedCallback callback =
+ applicationCallback != null ? applicationCallback : systemCallback;
+ ActivityRecord finalPrevTaskTopActivity = prevTaskTopActivity;
+ RemoteCallback onBackNavigationDone = new RemoteCallback(result -> onBackNavigationDone(
+ result, finalRemovedWindowContainer, finalBackType, task,
+ finalPrevTaskTopActivity));
return new BackNavigationInfo(backType,
topAppTarget,
screenshotSurface,
@@ -273,6 +306,39 @@
callback);
}
+ private void onBackNavigationDone(
+ Bundle result, WindowContainer windowContainer, int backType,
+ Task task, ActivityRecord prevTaskTopActivity) {
+ SurfaceControl surfaceControl = windowContainer.getSurfaceControl();
+ boolean triggerBack = result != null
+ ? result.getBoolean(BackNavigationInfo.KEY_TRIGGER_BACK)
+ : false;
+ ProtoLog.d(WM_DEBUG_BACK_PREVIEW, "onBackNavigationDone backType=%s, "
+ + "task=%s, prevTaskTopActivity=%s", backType, task, prevTaskTopActivity);
+
+ if (backType == BackNavigationInfo.TYPE_RETURN_TO_HOME && isAnimationEnabled()) {
+ if (triggerBack) {
+ if (surfaceControl != null && surfaceControl.isValid()) {
+ // When going back to home, hide the task surface before it is re-parented to
+ // avoid flicker.
+ SurfaceControl.Transaction t = windowContainer.getSyncTransaction();
+ t.hide(surfaceControl);
+ t.apply();
+ }
+ }
+ if (prevTaskTopActivity != null && !triggerBack) {
+ // Restore the launch-behind state.
+ task.mTaskSupervisor.scheduleLaunchTaskBehindComplete(prevTaskTopActivity.token);
+ prevTaskTopActivity.mLaunchTaskBehind = false;
+ ProtoLog.d(WM_DEBUG_BACK_PREVIEW,
+ "Setting Activity.mLauncherTaskBehind to false. Activity=%s",
+ prevTaskTopActivity);
+ }
+ } else {
+ task.mBackGestureStarted = false;
+ }
+ resetSurfaces(windowContainer);
+ }
private HardwareBuffer getActivitySnapshot(@NonNull Task task,
ComponentName activityComponent) {
diff --git a/services/core/java/com/android/server/wm/ContentRecorder.java b/services/core/java/com/android/server/wm/ContentRecorder.java
index 07a0c37..87523f4 100644
--- a/services/core/java/com/android/server/wm/ContentRecorder.java
+++ b/services/core/java/com/android/server/wm/ContentRecorder.java
@@ -17,6 +17,7 @@
package com.android.server.wm;
import static android.view.ContentRecordingSession.RECORD_CONTENT_DISPLAY;
+import static android.view.ContentRecordingSession.RECORD_CONTENT_TASK;
import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_CONTENT_RECORDING;
@@ -26,6 +27,7 @@
import android.graphics.Point;
import android.graphics.Rect;
import android.os.IBinder;
+import android.provider.DeviceConfig;
import android.view.ContentRecordingSession;
import android.view.Display;
import android.view.SurfaceControl;
@@ -39,6 +41,11 @@
final class ContentRecorder {
/**
+ * The key for accessing the device config that controls if task recording is supported.
+ */
+ @VisibleForTesting static final String KEY_RECORD_TASK_FEATURE = "record_task_content";
+
+ /**
* The display content this class is handling recording for.
*/
@NonNull
@@ -48,7 +55,7 @@
* The session for content recording, or null if this DisplayContent is not being used for
* recording.
*/
- @VisibleForTesting private ContentRecordingSession mContentRecordingSession = null;
+ private ContentRecordingSession mContentRecordingSession = null;
/**
* The WindowContainer for the level of the hierarchy to record.
@@ -187,6 +194,8 @@
mDisplayContent.mWmService.mTransactionFactory.get().remove(mRecordedSurface).apply();
mRecordedSurface = null;
clearContentRecordingSession();
+ // Do not need to force remove the VirtualDisplay; this is handled by the media
+ // projection service.
}
}
@@ -215,46 +224,12 @@
return;
}
- final int contentToRecord = mContentRecordingSession.getContentToRecord();
- if (contentToRecord != RECORD_CONTENT_DISPLAY) {
- // TODO(b/216625226) handle task-based recording
- // Not a valid region, or recording is disabled, so fall back to prior MediaProjection
- // approach.
- clearContentRecordingSession();
- ProtoLog.v(WM_DEBUG_CONTENT_RECORDING,
- "Unable to start recording due to invalid region for display %d",
- mDisplayContent.getDisplayId());
+ mRecordedWindowContainer = retrieveRecordedWindowContainer();
+ if (mRecordedWindowContainer == null) {
+ // Either the token is missing, or the window associated with the token is missing.
+ // Error has already been handled, so just leave.
return;
}
- // Given the WindowToken of the DisplayArea to record, retrieve the associated
- // SurfaceControl.
- IBinder tokenToRecord = mContentRecordingSession.getTokenToRecord();
- if (tokenToRecord == null) {
- // Unexpectedly missing token. Fall back to prior MediaProjection approach.
- clearContentRecordingSession();
- ProtoLog.v(WM_DEBUG_CONTENT_RECORDING,
- "Unable to start recording due to null token for display %d",
- mDisplayContent.getDisplayId());
- return;
- }
-
- final WindowContainer wc =
- mDisplayContent.mWmService.mWindowContextListenerController.getContainer(
- tokenToRecord);
- if (wc == null) {
- // Un-set the window token to record for this VirtualDisplay. Fall back to the
- // original MediaProjection approach.
- mDisplayContent.mWmService.mDisplayManagerInternal.setWindowManagerMirroring(
- mDisplayContent.getDisplayId(), false);
- clearContentRecordingSession();
- ProtoLog.v(WM_DEBUG_CONTENT_RECORDING,
- "Unable to retrieve window container to start recording for "
- + "display %d",
- mDisplayContent.getDisplayId());
- return;
- }
- // TODO(206461622) Migrate to using the RootDisplayArea
- mRecordedWindowContainer = wc.getDisplayContent();
final Point surfaceSize = fetchSurfaceSizeIfPresent();
if (surfaceSize == null) {
@@ -296,6 +271,107 @@
}
/**
+ * Retrieves the {@link WindowContainer} for the level of the hierarchy to start recording,
+ * indicated by the {@link #mContentRecordingSession}. Performs any error handling and state
+ * updates necessary if the {@link WindowContainer} could not be retrieved.
+ * {@link #mContentRecordingSession} must be non-null.
+ *
+ * @return a {@link WindowContainer} to record, or {@code null} if an error was encountered. The
+ * error is logged and any cleanup is handled.
+ */
+ @Nullable
+ private WindowContainer retrieveRecordedWindowContainer() {
+ final int contentToRecord = mContentRecordingSession.getContentToRecord();
+ // Given the WindowToken of the region to record, retrieve the associated
+ // SurfaceControl.
+ final IBinder tokenToRecord = mContentRecordingSession.getTokenToRecord();
+ if (tokenToRecord == null) {
+ handleStartRecordingFailed();
+ ProtoLog.v(WM_DEBUG_CONTENT_RECORDING,
+ "Unable to start recording due to null token for display %d",
+ mDisplayContent.getDisplayId());
+ return null;
+ }
+ switch (contentToRecord) {
+ case RECORD_CONTENT_DISPLAY:
+ final WindowContainer wc =
+ mDisplayContent.mWmService.mWindowContextListenerController.getContainer(
+ tokenToRecord);
+ if (wc == null) {
+ // Un-set the window token to record for this VirtualDisplay. Fall back to
+ // Display stack capture for the entire display.
+ mDisplayContent.mWmService.mDisplayManagerInternal.setWindowManagerMirroring(
+ mDisplayContent.getDisplayId(), false);
+ handleStartRecordingFailed();
+ ProtoLog.v(WM_DEBUG_CONTENT_RECORDING,
+ "Unable to retrieve window container to start recording for "
+ + "display %d", mDisplayContent.getDisplayId());
+ return null;
+ }
+ // TODO(206461622) Migrate to using the RootDisplayArea
+ return wc.getDisplayContent();
+ case RECORD_CONTENT_TASK:
+ if (!DeviceConfig.getBoolean(DeviceConfig.NAMESPACE_WINDOW_MANAGER,
+ KEY_RECORD_TASK_FEATURE, false)) {
+ handleStartRecordingFailed();
+ ProtoLog.v(WM_DEBUG_CONTENT_RECORDING,
+ "Unable to record task since feature is disabled %d",
+ mDisplayContent.getDisplayId());
+ return null;
+ }
+ Task taskToRecord = WindowContainer.fromBinder(tokenToRecord).asTask();
+ if (taskToRecord == null) {
+ handleStartRecordingFailed();
+ ProtoLog.v(WM_DEBUG_CONTENT_RECORDING,
+ "Unable to retrieve task to start recording for "
+ + "display %d", mDisplayContent.getDisplayId());
+ }
+ return taskToRecord;
+ default:
+ // Not a valid region, or recording is disabled, so fall back to Display stack
+ // capture for the entire display.
+ handleStartRecordingFailed();
+ ProtoLog.v(WM_DEBUG_CONTENT_RECORDING,
+ "Unable to start recording due to invalid region for display %d",
+ mDisplayContent.getDisplayId());
+ return null;
+ }
+ }
+
+ /**
+ * Exit this recording session.
+ * <p>
+ * If this is a task session, tear down the recording entirely. Do not fall back
+ * to recording the entire display on the display stack; this would surprise the user
+ * given they selected task capture.
+ * </p><p>
+ * If this is a display session, just stop recording by layer mirroring. Fall back to recording
+ * from the display stack.
+ * </p>
+ */
+ private void handleStartRecordingFailed() {
+ final boolean shouldExitTaskRecording = mContentRecordingSession != null
+ && mContentRecordingSession.getContentToRecord() == RECORD_CONTENT_TASK;
+ if (shouldExitTaskRecording) {
+ // Clean up the cached session first, since tearing down the display will generate
+ // display
+ // events which will trickle back to here.
+ clearContentRecordingSession();
+ tearDownVirtualDisplay();
+ } else {
+ clearContentRecordingSession();
+ }
+ }
+
+ /**
+ * Ensure recording does not fall back to the display stack; ensure the recording is stopped
+ * and the client notified by tearing down the virtual display.
+ */
+ private void tearDownVirtualDisplay() {
+ // TODO(b/219761722) Clean up the VirtualDisplay if task mirroring fails
+ }
+
+ /**
* Apply transformations to the mirrored surface to ensure the captured contents are scaled to
* fit and centred in the output surface.
*
diff --git a/services/core/java/com/android/server/wm/DisplayContent.java b/services/core/java/com/android/server/wm/DisplayContent.java
index 59ba4e7..f5ace6c 100644
--- a/services/core/java/com/android/server/wm/DisplayContent.java
+++ b/services/core/java/com/android/server/wm/DisplayContent.java
@@ -128,7 +128,6 @@
import static com.android.server.wm.DisplayContentProto.ROOT_DISPLAY_AREA;
import static com.android.server.wm.DisplayContentProto.SCREEN_ROTATION_ANIMATION;
import static com.android.server.wm.DisplayContentProto.SLEEP_TOKENS;
-import static com.android.server.wm.SurfaceAnimator.ANIMATION_TYPE_ALL;
import static com.android.server.wm.SurfaceAnimator.ANIMATION_TYPE_APP_TRANSITION;
import static com.android.server.wm.SurfaceAnimator.ANIMATION_TYPE_RECENTS;
import static com.android.server.wm.SurfaceAnimator.ANIMATION_TYPE_WINDOW_ANIMATION;
@@ -145,7 +144,6 @@
import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
import static com.android.server.wm.WindowManagerService.H.REPORT_HARD_KEYBOARD_STATUS_CHANGE;
import static com.android.server.wm.WindowManagerService.H.WINDOW_HIDE_TIMEOUT;
-import static com.android.server.wm.WindowManagerService.LAYOUT_REPEAT_THRESHOLD;
import static com.android.server.wm.WindowManagerService.UPDATE_FOCUS_PLACING_SURFACES;
import static com.android.server.wm.WindowManagerService.UPDATE_FOCUS_WILL_ASSIGN_LAYERS;
import static com.android.server.wm.WindowManagerService.UPDATE_FOCUS_WILL_PLACE_SURFACES;
@@ -4504,56 +4502,38 @@
mTmpUpdateAllDrawn.clear();
- int repeats = 0;
- do {
- repeats++;
- if (repeats > 6) {
- Slog.w(TAG, "Animation repeat aborted after too many iterations");
- clearLayoutNeeded();
- break;
- }
+ if (DEBUG_LAYOUT_REPEATS) surfacePlacer.debugLayoutRepeats("On entry to LockedInner",
+ pendingLayoutChanges);
- if (DEBUG_LAYOUT_REPEATS) surfacePlacer.debugLayoutRepeats("On entry to LockedInner",
- pendingLayoutChanges);
+ if ((pendingLayoutChanges & FINISH_LAYOUT_REDO_WALLPAPER) != 0) {
+ mWallpaperController.adjustWallpaperWindows();
+ }
- if ((pendingLayoutChanges & FINISH_LAYOUT_REDO_WALLPAPER) != 0) {
- mWallpaperController.adjustWallpaperWindows();
- }
-
- if ((pendingLayoutChanges & FINISH_LAYOUT_REDO_CONFIG) != 0) {
- if (DEBUG_LAYOUT) Slog.v(TAG, "Computing new config from layout");
- if (updateOrientation()) {
- setLayoutNeeded();
- sendNewConfiguration();
- }
- }
-
- if ((pendingLayoutChanges & FINISH_LAYOUT_REDO_LAYOUT) != 0) {
+ if ((pendingLayoutChanges & FINISH_LAYOUT_REDO_CONFIG) != 0) {
+ if (DEBUG_LAYOUT) Slog.v(TAG, "Computing new config from layout");
+ if (updateOrientation()) {
setLayoutNeeded();
+ sendNewConfiguration();
}
+ }
- // FIRST LOOP: Perform a layout, if needed.
- if (repeats < LAYOUT_REPEAT_THRESHOLD) {
- performLayout(repeats == 1, false /* updateInputWindows */);
- } else {
- Slog.w(TAG, "Layout repeat skipped after too many iterations");
- }
+ if ((pendingLayoutChanges & FINISH_LAYOUT_REDO_LAYOUT) != 0) {
+ setLayoutNeeded();
+ }
- // FIRST AND ONE HALF LOOP: Make WindowManagerPolicy think it is animating.
- pendingLayoutChanges = 0;
+ // Perform a layout, if needed.
+ performLayout(true /* initial */, false /* updateInputWindows */);
+ pendingLayoutChanges = 0;
- Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "applyPostLayoutPolicy");
- try {
- mDisplayPolicy.beginPostLayoutPolicyLw();
- forAllWindows(mApplyPostLayoutPolicy, true /* traverseTopToBottom */);
- pendingLayoutChanges |= mDisplayPolicy.finishPostLayoutPolicyLw();
- } finally {
- Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
- }
- if (DEBUG_LAYOUT_REPEATS) surfacePlacer.debugLayoutRepeats(
- "after finishPostLayoutPolicyLw", pendingLayoutChanges);
- mInsetsStateController.onPostLayout();
- } while (pendingLayoutChanges != 0);
+ Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "applyPostLayoutPolicy");
+ try {
+ mDisplayPolicy.beginPostLayoutPolicyLw();
+ forAllWindows(mApplyPostLayoutPolicy, true /* traverseTopToBottom */);
+ mDisplayPolicy.finishPostLayoutPolicyLw();
+ } finally {
+ Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
+ }
+ mInsetsStateController.onPostLayout();
mTmpApplySurfaceChangesTransactionState.reset();
@@ -5020,10 +5000,6 @@
// docked divider while keeping the app itself below the docked divider, so instead
// we will put the docked divider below the IME. @see #assignRelativeLayerForImeTargetChild
//
- // In the case the IME target is animating, the animation Z order may be different
- // than the WindowContainer Z order, so it's difficult to be sure we have the correct
- // IME target. In this case we just layer the IME over its parent surface.
- //
// In the case where we have no IME target we let its window parent to place it.
//
// Keep IME window in surface parent as long as app's starting window
@@ -5039,9 +5015,7 @@
// We don't need to set relative layer if the IME target in non-multi-window
// mode is the activity main window since updateImeParent will ensure the IME
// surface be attached on the fullscreen activity.
- && imeTarget.mAttrs.type != TYPE_BASE_APPLICATION
- && imeTarget.mToken.getActivity(app -> app.isAnimating(TRANSITION | PARENTS,
- ANIMATION_TYPE_ALL & ~ANIMATION_TYPE_RECENTS)) == null;
+ && imeTarget.mAttrs.type != TYPE_BASE_APPLICATION;
if (canImeTargetSetRelativeLayer) {
mImeWindowsContainer.assignRelativeLayer(t, imeTarget.getSurfaceControl(),
// TODO: We need to use an extra level on the app surface to ensure
diff --git a/services/core/java/com/android/server/wm/DisplayPolicy.java b/services/core/java/com/android/server/wm/DisplayPolicy.java
index 4148d8b..88d7dff 100644
--- a/services/core/java/com/android/server/wm/DisplayPolicy.java
+++ b/services/core/java/com/android/server/wm/DisplayPolicy.java
@@ -42,11 +42,9 @@
import static android.view.WindowManager.LayoutParams.FIRST_SYSTEM_WINDOW;
import static android.view.WindowManager.LayoutParams.FLAG_ALLOW_LOCK_WHILE_SCREEN_ON;
import static android.view.WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS;
-import static android.view.WindowManager.LayoutParams.FLAG_FORCE_NOT_FULLSCREEN;
import static android.view.WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE;
import static android.view.WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS;
import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_FORCE_DRAW_BAR_BACKGROUNDS;
-import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_FORCE_SHOW_STATUS_BAR;
import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_INTERCEPT_GLOBAL_DRAG_AND_DROP;
import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_TRUSTED_OVERLAY;
import static android.view.WindowManager.LayoutParams.TYPE_BASE_APPLICATION;
@@ -79,7 +77,6 @@
import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_SCREEN_ON;
import static com.android.server.policy.PhoneWindowManager.TOAST_WINDOW_TIMEOUT;
-import static com.android.server.policy.WindowManagerPolicy.FINISH_LAYOUT_REDO_LAYOUT;
import static com.android.server.policy.WindowManagerPolicy.TRANSIT_ENTER;
import static com.android.server.policy.WindowManagerPolicy.TRANSIT_EXIT;
import static com.android.server.policy.WindowManagerPolicy.TRANSIT_HIDE;
@@ -117,6 +114,7 @@
import android.util.ArraySet;
import android.util.PrintWriterPrinter;
import android.util.Slog;
+import android.util.SparseArray;
import android.view.DisplayCutout;
import android.view.DisplayInfo;
import android.view.Gravity;
@@ -136,6 +134,7 @@
import android.view.WindowManagerGlobal;
import android.view.WindowManagerPolicyConstants;
import android.view.accessibility.AccessibilityManager;
+import android.window.ClientWindowFrames;
import com.android.internal.R;
import com.android.internal.annotations.VisibleForTesting;
@@ -340,15 +339,12 @@
private static final Rect sTmpRect2 = new Rect();
private static final Rect sTmpLastParentFrame = new Rect();
private static final Rect sTmpDisplayCutoutSafe = new Rect();
- private static final Rect sTmpDisplayFrame = new Rect();
- private static final Rect sTmpParentFrame = new Rect();
- private static final Rect sTmpFrame = new Rect();
+ private static final ClientWindowFrames sTmpClientFrames = new ClientWindowFrames();
private final WindowLayout mWindowLayout = new WindowLayout();
private WindowState mTopFullscreenOpaqueWindowState;
private boolean mTopIsFullscreen;
- private boolean mForceStatusBar;
private int mNavBarOpacityMode = NAV_BAR_OPAQUE_WHEN_FREEFORM_OR_DOCKED;
private boolean mForceShowSystemBars;
@@ -940,6 +936,26 @@
break;
}
+ if (LayoutParams.isSystemAlertWindowType(attrs.type)) {
+ float maxOpacity = mService.mMaximumObscuringOpacityForTouch;
+ if (attrs.alpha > maxOpacity
+ && (attrs.flags & FLAG_NOT_TOUCHABLE) != 0
+ && (attrs.privateFlags & PRIVATE_FLAG_TRUSTED_OVERLAY) == 0) {
+ // The app is posting a SAW with the intent of letting touches pass through, but
+ // they are going to be deemed untrusted and will be blocked. Try to honor the
+ // intent of letting touches pass through at the cost of 0.2 opacity for app
+ // compatibility reasons. More details on b/218777508.
+ Slog.w(TAG, String.format(
+ "App %s has a system alert window (type = %d) with FLAG_NOT_TOUCHABLE and "
+ + "LayoutParams.alpha = %.2f > %.2f, setting alpha to %.2f to "
+ + "let touches pass through (if this is isn't desirable, remove "
+ + "flag FLAG_NOT_TOUCHABLE).",
+ attrs.packageName, attrs.type, attrs.alpha, maxOpacity, maxOpacity));
+ attrs.alpha = maxOpacity;
+ win.mWinAnimator.mAlpha = maxOpacity;
+ }
+ }
+
// Check if alternate bars positions were updated.
if (mStatusBarAlt == win) {
mStatusBarAltPosition = getAltBarPosition(attrs);
@@ -1136,9 +1152,8 @@
}
},
- // For IME we use regular frame.
(displayFrames, windowContainer, inOutFrame) -> {
- inOutFrame.set(win.getFrame());
+ // For IME, we don't modify the frame.
});
mDisplayContent.setInsetProvider(ITYPE_BOTTOM_MANDATORY_GESTURES, win,
@@ -1473,9 +1488,30 @@
displayFrames.mInsetsState, displayFrames.mDisplayCutoutSafe,
displayFrames.mUnrestricted, win.getWindowingMode(), UNSPECIFIED_LENGTH,
UNSPECIFIED_LENGTH, win.getRequestedVisibilities(),
- null /* attachedWindowFrame */, win.mGlobalScale,
- sTmpDisplayFrame, sTmpParentFrame, sTmpFrame);
- controller.computeSimulatedState(win, displayFrames, sTmpFrame);
+ null /* attachedWindowFrame */, win.mGlobalScale, sTmpClientFrames);
+ final SparseArray<InsetsSource> sources = win.getProvidedInsetsSources();
+ final InsetsState state = displayFrames.mInsetsState;
+ for (int index = sources.size() - 1; index >= 0; index--) {
+ final int type = sources.keyAt(index);
+ state.addSource(controller.getSourceProvider(type).createSimulatedSource(
+ displayFrames, sTmpClientFrames.frame));
+ }
+ }
+ }
+
+ // TODO(b/161810301): No one is calling this since we haven't moved window layout to the client.
+ // When that happens, this should be called when the display rotation is
+ // changed, so that we can dispatch the correct insets to all the clients
+ // before the insets source windows report their frames to the server.
+ void updateInsetsSourceFramesExceptIme(DisplayFrames displayFrames) {
+ for (int i = mInsetsSourceWindowsExceptIme.size() - 1; i >= 0; i--) {
+ final WindowState win = mInsetsSourceWindowsExceptIme.valueAt(i);
+ mWindowLayout.computeFrames(win.getLayoutingAttrs(displayFrames.mRotation),
+ displayFrames.mInsetsState, displayFrames.mDisplayCutoutSafe,
+ displayFrames.mUnrestricted, win.getWindowingMode(), UNSPECIFIED_LENGTH,
+ UNSPECIFIED_LENGTH, win.getRequestedVisibilities(),
+ null /* attachedWindowFrame */, win.mGlobalScale, sTmpClientFrames);
+ win.updateSourceFrame(sTmpClientFrames.frame);
}
}
@@ -1504,10 +1540,6 @@
displayFrames = win.getDisplayFrames(displayFrames);
final WindowManager.LayoutParams attrs = win.getLayoutingAttrs(displayFrames.mRotation);
- final WindowFrames windowFrames = win.getWindowFrames();
- final Rect pf = windowFrames.mParentFrame;
- final Rect df = windowFrames.mDisplayFrame;
- final Rect f = windowFrames.mFrame;
final Rect attachedWindowFrame = attached != null ? attached.getFrame() : null;
// If this window has different LayoutParams for rotations, we cannot trust its requested
@@ -1516,27 +1548,12 @@
final int requestedWidth = trustedSize ? win.mRequestedWidth : UNSPECIFIED_LENGTH;
final int requestedHeight = trustedSize ? win.mRequestedHeight : UNSPECIFIED_LENGTH;
- sTmpLastParentFrame.set(pf);
-
- final boolean clippedByDisplayCutout = mWindowLayout.computeFrames(attrs,
- win.getInsetsState(), displayFrames.mDisplayCutoutSafe,
+ mWindowLayout.computeFrames(attrs, win.getInsetsState(), displayFrames.mDisplayCutoutSafe,
win.getBounds(), win.getWindowingMode(), requestedWidth, requestedHeight,
win.getRequestedVisibilities(), attachedWindowFrame, win.mGlobalScale,
- df, pf, f);
- windowFrames.setParentFrameWasClippedByDisplayCutout(clippedByDisplayCutout);
+ sTmpClientFrames);
- if (DEBUG_LAYOUT) Slog.v(TAG, "Compute frame " + attrs.getTitle()
- + ": sim=#" + Integer.toHexString(attrs.softInputMode)
- + " attach=" + attached + " type=" + attrs.type
- + " flags=" + ViewDebug.flagsToString(LayoutParams.class, "flags", attrs.flags)
- + " pf=" + pf.toShortString() + " df=" + df.toShortString()
- + " f=" + f.toShortString());
-
- if (!sTmpLastParentFrame.equals(pf)) {
- windowFrames.setContentChanged(true);
- }
-
- win.setFrame();
+ win.setFrames(sTmpClientFrames);
}
WindowState getTopFullscreenOpaqueWindow() {
@@ -1558,7 +1575,6 @@
mStatusBarBackgroundWindows.clear();
mStatusBarColorCheckedBounds.setEmpty();
mStatusBarBackgroundCheckedBounds.setEmpty();
- mForceStatusBar = false;
mAllowLockscreenWhenOn = false;
mShowingDream = false;
@@ -1599,9 +1615,6 @@
&& attrs.type < FIRST_SYSTEM_WINDOW;
if (mTopFullscreenOpaqueWindowState == null) {
final int fl = attrs.flags;
- if ((fl & FLAG_FORCE_NOT_FULLSCREEN) != 0) {
- mForceStatusBar = true;
- }
if (win.isDreamWindow()) {
// If the lockscreen was showing when the dream started then wait
// for the dream to draw before hiding the lockscreen.
@@ -1710,21 +1723,9 @@
}
/**
- * Called following layout of all windows and after policy has been applied
- * to each window. If in this function you do
- * something that may have modified the animation state of another window,
- * be sure to return non-zero in order to perform another pass through layout.
- *
- * @return Return any bit set of
- * {@link WindowManagerPolicy#FINISH_LAYOUT_REDO_LAYOUT},
- * {@link WindowManagerPolicy#FINISH_LAYOUT_REDO_CONFIG},
- * {@link WindowManagerPolicy#FINISH_LAYOUT_REDO_WALLPAPER}, or
- * {@link WindowManagerPolicy#FINISH_LAYOUT_REDO_ANIM}.
+ * Called following layout of all windows and after policy has been applied to each window.
*/
- public int finishPostLayoutPolicyLw() {
- int changes = 0;
- boolean topIsFullscreen = false;
-
+ public void finishPostLayoutPolicyLw() {
// If we are not currently showing a dream then remember the current
// lockscreen state. We will use this to determine whether the dream
// started while the lockscreen was showing and remember this state
@@ -1733,41 +1734,6 @@
mDreamingLockscreen = mService.mPolicy.isKeyguardShowingAndNotOccluded();
}
- if (getStatusBar() != null) {
- if (DEBUG_LAYOUT) Slog.i(TAG, "force=" + mForceStatusBar
- + " top=" + mTopFullscreenOpaqueWindowState);
- final boolean forceShowStatusBar = (getStatusBar().getAttrs().privateFlags
- & PRIVATE_FLAG_FORCE_SHOW_STATUS_BAR) != 0;
-
- boolean topAppHidesStatusBar = topAppHidesStatusBar();
- if (mForceStatusBar || forceShowStatusBar) {
- if (DEBUG_LAYOUT) Slog.v(TAG, "Showing status bar: forced");
- // Maintain fullscreen layout until incoming animation is complete.
- topIsFullscreen = mTopIsFullscreen && mStatusBar.isAnimatingLw();
- } else if (mTopFullscreenOpaqueWindowState != null) {
- topIsFullscreen = topAppHidesStatusBar;
- // The subtle difference between the window for mTopFullscreenOpaqueWindowState
- // and mTopIsFullscreen is that mTopIsFullscreen is set only if the window
- // requests to hide the status bar. Not sure if there is another way that to be the
- // case though.
- if (!topIsFullscreen) {
- topAppHidesStatusBar = false;
- }
- }
- StatusBarManagerInternal statusBar = getStatusBarManagerInternal();
- if (statusBar != null) {
- statusBar.setTopAppHidesStatusBar(topAppHidesStatusBar);
- }
- }
-
- if (mTopIsFullscreen != topIsFullscreen) {
- if (!topIsFullscreen) {
- // Force another layout when status bar becomes fully shown.
- changes |= FINISH_LAYOUT_REDO_LAYOUT;
- }
- mTopIsFullscreen = topIsFullscreen;
- }
-
updateSystemBarAttributes();
if (mShowingDream != mLastShowingDream) {
@@ -1777,7 +1743,6 @@
}
mService.mPolicy.setAllowLockscreenWhenOn(getDisplayId(), mAllowLockscreenWhenOn);
- return changes;
}
/**
@@ -2441,6 +2406,18 @@
mForceShowSystemBars = multiWindowTaskVisible || freeformRootTaskVisible;
mDisplayContent.getInsetsPolicy().updateBarControlTarget(win);
+ final boolean topAppHidesStatusBar = topAppHidesStatusBar();
+ if (getStatusBar() != null) {
+ final StatusBarManagerInternal statusBar = getStatusBarManagerInternal();
+ if (statusBar != null) {
+ statusBar.setTopAppHidesStatusBar(topAppHidesStatusBar);
+ }
+ }
+
+ // If the top app is not fullscreen, only the default rotation animation is allowed.
+ mTopIsFullscreen = topAppHidesStatusBar
+ && (mNotificationShade == null || !mNotificationShade.isVisible());
+
int appearance = APPEARANCE_OPAQUE_NAVIGATION_BARS | APPEARANCE_OPAQUE_STATUS_BARS;
appearance = configureStatusBarOpacity(appearance);
appearance = configureNavBarOpacity(appearance, multiWindowTaskVisible,
@@ -2781,7 +2758,6 @@
}
}
pw.print(prefix); pw.print("mTopIsFullscreen="); pw.println(mTopIsFullscreen);
- pw.print(prefix); pw.print("mForceStatusBar="); pw.print(mForceStatusBar);
pw.print(prefix); pw.print("mForceShowNavigationBarEnabled=");
pw.print(mForceShowNavigationBarEnabled);
pw.print(" mAllowLockscreenWhenOn="); pw.println(mAllowLockscreenWhenOn);
diff --git a/services/core/java/com/android/server/wm/ImeInsetsSourceProvider.java b/services/core/java/com/android/server/wm/ImeInsetsSourceProvider.java
index 199517c..0d4cfa3 100644
--- a/services/core/java/com/android/server/wm/ImeInsetsSourceProvider.java
+++ b/services/core/java/com/android/server/wm/ImeInsetsSourceProvider.java
@@ -29,6 +29,7 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
+import android.graphics.Rect;
import android.os.Trace;
import android.util.proto.ProtoOutputStream;
import android.view.InsetsSource;
@@ -79,8 +80,8 @@
}
@Override
- void updateSourceFrame() {
- super.updateSourceFrame();
+ void updateSourceFrame(Rect frame) {
+ super.updateSourceFrame(frame);
onSourceChanged();
}
diff --git a/services/core/java/com/android/server/wm/InsetsPolicy.java b/services/core/java/com/android/server/wm/InsetsPolicy.java
index 3951c56..9844cb5 100644
--- a/services/core/java/com/android/server/wm/InsetsPolicy.java
+++ b/services/core/java/com/android/server/wm/InsetsPolicy.java
@@ -344,7 +344,6 @@
// Navigation bar doesn't get influenced by anything else
if (type == ITYPE_NAVIGATION_BAR || type == ITYPE_EXTRA_NAVIGATION_BAR) {
- state.removeSource(ITYPE_IME);
state.removeSource(ITYPE_STATUS_BAR);
state.removeSource(ITYPE_CLIMATE_BAR);
state.removeSource(ITYPE_CAPTION_BAR);
diff --git a/services/core/java/com/android/server/wm/InsetsSourceProvider.java b/services/core/java/com/android/server/wm/InsetsSourceProvider.java
index 047bf2f..f3f08b2 100644
--- a/services/core/java/com/android/server/wm/InsetsSourceProvider.java
+++ b/services/core/java/com/android/server/wm/InsetsSourceProvider.java
@@ -84,6 +84,7 @@
private TriConsumer<DisplayFrames, WindowContainer, Rect> mImeFrameProvider;
private final Rect mImeOverrideFrame = new Rect();
private boolean mIsLeashReadyForDispatching;
+ private final Rect mSourceFrame = new Rect();
private final Rect mLastSourceFrame = new Rect();
private final Consumer<Transaction> mSetLeashPositionConsumer = t -> {
@@ -183,8 +184,8 @@
mImeFrameProvider = imeFrameProvider;
if (windowContainer == null) {
setServerVisible(false);
- mSource.setFrame(new Rect());
mSource.setVisibleFrame(null);
+ mSourceFrame.setEmpty();
} else {
mWindowContainer.getProvidedInsetsSources().put(mSource.getType(), mSource);
if (mControllable) {
@@ -208,7 +209,7 @@
* The source frame can affect the layout of other windows, so this should be called once the
* window container gets laid out.
*/
- void updateSourceFrame() {
+ void updateSourceFrame(Rect frame) {
if (mWindowContainer == null) {
return;
}
@@ -230,39 +231,25 @@
return;
}
- if (win.mGivenInsetsPending) {
- // If the given insets are pending, they are not reliable for now. The source frame
- // should be updated after the new given insets are sent to window manager.
- return;
- }
-
- // Make sure we set the valid source frame only when server visible is true, because the
- // frame may not yet determined that server side doesn't think the window is ready to
- // visible. (i.e. No surface, pending insets that were given during layout, etc..)
- if (mServerVisible) {
- mTmpRect.set(win.getFrame());
- if (mFrameProvider != null) {
- mFrameProvider.accept(mWindowContainer.getDisplayContent().mDisplayFrames,
- mWindowContainer, mTmpRect);
- } else {
- mTmpRect.inset(win.mGivenContentInsets);
- }
+ mSourceFrame.set(frame);
+ if (mFrameProvider != null) {
+ mFrameProvider.accept(mWindowContainer.getDisplayContent().mDisplayFrames,
+ mWindowContainer, mSourceFrame);
} else {
- mTmpRect.setEmpty();
+ mSourceFrame.inset(win.mGivenContentInsets);
}
- mSource.setFrame(mTmpRect);
+ updateSourceFrameForServerVisibility();
if (mImeFrameProvider != null) {
- mImeOverrideFrame.set(win.getFrame());
+ mImeOverrideFrame.set(frame);
mImeFrameProvider.accept(mWindowContainer.getDisplayContent().mDisplayFrames,
- mWindowContainer,
- mImeOverrideFrame);
+ mWindowContainer, mImeOverrideFrame);
}
if (win.mGivenVisibleInsets.left != 0 || win.mGivenVisibleInsets.top != 0
|| win.mGivenVisibleInsets.right != 0
|| win.mGivenVisibleInsets.bottom != 0) {
- mTmpRect.set(win.getFrame());
+ mTmpRect.set(frame);
mTmpRect.inset(win.mGivenVisibleInsets);
mSource.setVisibleFrame(mTmpRect);
} else {
@@ -270,13 +257,24 @@
}
}
+ private void updateSourceFrameForServerVisibility() {
+ // Make sure we set the valid source frame only when server visible is true, because the
+ // frame may not yet determined that server side doesn't think the window is ready to
+ // visible. (i.e. No surface, pending insets that were given during layout, etc..)
+ if (mServerVisible) {
+ mSource.setFrame(mSourceFrame);
+ } else {
+ mSource.setFrame(0, 0, 0, 0);
+ }
+ }
+
/** @return A new source computed by the specified window frame in the given display frames. */
- InsetsSource createSimulatedSource(DisplayFrames displayFrames, Rect winFrame) {
+ InsetsSource createSimulatedSource(DisplayFrames displayFrames, Rect frame) {
// Don't copy visible frame because it might not be calculated in the provided display
// frames and it is not significant for this usage.
final InsetsSource source = new InsetsSource(mSource.getType());
source.setVisible(mSource.isVisible());
- mTmpRect.set(winFrame);
+ mTmpRect.set(frame);
if (mFrameProvider != null) {
mFrameProvider.accept(displayFrames, mWindowContainer, mTmpRect);
}
@@ -296,7 +294,6 @@
? windowState.wouldBeVisibleIfPolicyIgnored() && windowState.isVisibleByPolicy()
: mWindowContainer.isVisibleRequested();
setServerVisible(isServerVisible);
- updateSourceFrame();
if (mControl != null) {
boolean changed = false;
final Point position = getWindowFrameSurfacePosition();
@@ -496,6 +493,7 @@
@VisibleForTesting
void setServerVisible(boolean serverVisible) {
mServerVisible = serverVisible;
+ updateSourceFrameForServerVisibility();
updateVisibility();
}
diff --git a/services/core/java/com/android/server/wm/InsetsStateController.java b/services/core/java/com/android/server/wm/InsetsStateController.java
index 78608e2..a19d72e 100644
--- a/services/core/java/com/android/server/wm/InsetsStateController.java
+++ b/services/core/java/com/android/server/wm/InsetsStateController.java
@@ -30,7 +30,6 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
-import android.graphics.Rect;
import android.os.Trace;
import android.util.ArrayMap;
import android.util.ArraySet;
@@ -204,23 +203,6 @@
}
}
- /**
- * Computes insets state of the insets provider window in the display frames.
- *
- * @param win The owner window of insets provider.
- * @param displayFrames The display frames to create insets source.
- * @param winFrame The frame of the insets source window.
- */
- void computeSimulatedState(WindowState win, DisplayFrames displayFrames, Rect winFrame) {
- final InsetsState state = displayFrames.mInsetsState;
- for (int i = mProviders.size() - 1; i >= 0; i--) {
- final WindowContainerInsetsSourceProvider provider = mProviders.valueAt(i);
- if (provider.mWindowContainer == win) {
- state.addSource(provider.createSimulatedSource(displayFrames, winFrame));
- }
- }
- }
-
boolean isFakeTarget(@InternalInsetsType int type, InsetsControlTarget target) {
return mTypeFakeControlTargetMap.get(type) == target;
}
diff --git a/services/core/java/com/android/server/wm/Session.java b/services/core/java/com/android/server/wm/Session.java
index 0c60919..9ad25ac8 100644
--- a/services/core/java/com/android/server/wm/Session.java
+++ b/services/core/java/com/android/server/wm/Session.java
@@ -232,14 +232,14 @@
int requestedWidth, int requestedHeight, int viewFlags, int flags,
ClientWindowFrames outFrames, MergedConfiguration mergedConfiguration,
SurfaceControl outSurfaceControl, InsetsState outInsetsState,
- InsetsSourceControl[] outActiveControls) {
+ InsetsSourceControl[] outActiveControls, Bundle outSyncSeqIdBundle) {
if (false) Slog.d(TAG_WM, ">>>>>> ENTERED relayout from "
+ Binder.getCallingPid());
Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, mRelayoutTag);
int res = mService.relayoutWindow(this, window, attrs,
requestedWidth, requestedHeight, viewFlags, flags,
outFrames, mergedConfiguration, outSurfaceControl, outInsetsState,
- outActiveControls);
+ outActiveControls, outSyncSeqIdBundle);
Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
if (false) Slog.d(TAG_WM, "<<<<<< EXITING relayout to "
+ Binder.getCallingPid());
@@ -265,9 +265,9 @@
@Override
public void finishDrawing(IWindow window,
- @Nullable SurfaceControl.Transaction postDrawTransaction) {
+ @Nullable SurfaceControl.Transaction postDrawTransaction, int seqId) {
if (DEBUG) Slog.v(TAG_WM, "IWindow finishDrawing called for " + window);
- mService.finishDrawingWindow(this, window, postDrawTransaction);
+ mService.finishDrawingWindow(this, window, postDrawTransaction, seqId);
}
@Override
diff --git a/services/core/java/com/android/server/wm/Task.java b/services/core/java/com/android/server/wm/Task.java
index cd7ebe3..f71bd72 100644
--- a/services/core/java/com/android/server/wm/Task.java
+++ b/services/core/java/com/android/server/wm/Task.java
@@ -72,6 +72,7 @@
import static com.android.internal.policy.DecorView.DECOR_SHADOW_FOCUSED_HEIGHT_IN_DIP;
import static com.android.internal.policy.DecorView.DECOR_SHADOW_UNFOCUSED_HEIGHT_IN_DIP;
import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_ADD_REMOVE;
+import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_BACK_PREVIEW;
import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_LOCKTASK;
import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_RECENTS_ANIMATIONS;
import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_STATES;
@@ -609,6 +610,12 @@
boolean mLastSurfaceShowing = true;
+ /**
+ * Tracks if a back gesture is in progress.
+ * Skips any system transition animations if this is set to {@code true}.
+ */
+ boolean mBackGestureStarted = false;
+
private Task(ActivityTaskManagerService atmService, int _taskId, Intent _intent,
Intent _affinityIntent, String _affinity, String _rootAffinity,
ComponentName _realActivity, ComponentName _origActivity, boolean _rootWasReset,
@@ -1623,12 +1630,16 @@
}
ActivityRecord performClearTop(ActivityRecord newR, int launchFlags) {
+ // The task should be preserved for putting new activity in case the last activity is
+ // finished if it is normal launch mode and not single top ("clear-task-top").
+ mReuseTask = true;
mTaskSupervisor.beginDeferResume();
final ActivityRecord result;
try {
result = clearTopActivities(newR, launchFlags);
} finally {
mTaskSupervisor.endDeferResume();
+ mReuseTask = false;
}
return result;
}
@@ -3322,6 +3333,14 @@
}
});
}
+ } else if (mBackGestureStarted) {
+ // Cancel playing transitions if a back navigation animation is in progress.
+ // This bit is set by {@link BackNavigationController} when a back gesture is started.
+ // It is used as a one-off transition overwrite that is cleared when the back gesture
+ // is committed and triggers a transition, or when the gesture is cancelled.
+ mBackGestureStarted = false;
+ mDisplayContent.mSkipAppTransitionAnimation = true;
+ ProtoLog.d(WM_DEBUG_BACK_PREVIEW, "Skipping app transition animation. task=%s", this);
} else {
super.applyAnimationUnchecked(lp, enter, transit, isVoiceInteraction, sources);
}
diff --git a/services/core/java/com/android/server/wm/TaskDisplayArea.java b/services/core/java/com/android/server/wm/TaskDisplayArea.java
index 2f50b14..7bb7870 100644
--- a/services/core/java/com/android/server/wm/TaskDisplayArea.java
+++ b/services/core/java/com/android/server/wm/TaskDisplayArea.java
@@ -824,9 +824,19 @@
}
void setBackgroundColor(@ColorInt int colorInt) {
+ setBackgroundColor(colorInt, false /* restore */);
+ }
+
+ void setBackgroundColor(@ColorInt int colorInt, boolean restore) {
mBackgroundColor = colorInt;
Color color = Color.valueOf(colorInt);
- mColorLayerCounter++;
+
+ // We don't want to increment the mColorLayerCounter if we are restoring the background
+ // color after a surface migration because in that case the mColorLayerCounter already
+ // accounts for setting that background color.
+ if (!restore) {
+ mColorLayerCounter++;
+ }
// Only apply the background color if the TDA is actually attached and has a valid surface
// to set the background color on. We still want to keep track of the background color state
@@ -855,7 +865,7 @@
super.migrateToNewSurfaceControl(t);
if (mColorLayerCounter > 0) {
- setBackgroundColor(mBackgroundColor);
+ setBackgroundColor(mBackgroundColor, true /* restore */);
}
if (mSplitScreenDividerAnchor == null) {
diff --git a/services/core/java/com/android/server/wm/TaskFragment.java b/services/core/java/com/android/server/wm/TaskFragment.java
index 597d29f..2ac41a7 100644
--- a/services/core/java/com/android/server/wm/TaskFragment.java
+++ b/services/core/java/com/android/server/wm/TaskFragment.java
@@ -63,8 +63,6 @@
import static com.android.server.wm.TaskFragmentProto.MIN_HEIGHT;
import static com.android.server.wm.TaskFragmentProto.MIN_WIDTH;
import static com.android.server.wm.TaskFragmentProto.WINDOW_CONTAINER;
-import static com.android.server.wm.WindowContainer.AnimationFlags.CHILDREN;
-import static com.android.server.wm.WindowContainer.AnimationFlags.TRANSITION;
import static com.android.server.wm.WindowContainerChildProto.TASK_FRAGMENT;
import android.annotation.IntDef;
@@ -1461,7 +1459,8 @@
// next activity.
final boolean lastResumedCanPip = prev.checkEnterPictureInPictureState(
"shouldAutoPipWhilePausing", userLeaving);
- if (lastResumedCanPip && prev.pictureInPictureArgs.isAutoEnterEnabled()) {
+ if (userLeaving && lastResumedCanPip
+ && prev.pictureInPictureArgs.isAutoEnterEnabled()) {
shouldAutoPip = true;
} else if (!lastResumedCanPip) {
// If the flag RESUME_WHILE_PAUSING is set, then continue to schedule the previous
@@ -2370,8 +2369,7 @@
if (!hasChild()) {
return false;
}
- return isAnimating(TRANSITION | CHILDREN, WindowState.EXIT_ANIMATING_TYPES)
- || inTransition();
+ return isExitAnimationRunningSelfOrChild() || inTransition();
}
@Override
diff --git a/services/core/java/com/android/server/wm/WindowContainer.java b/services/core/java/com/android/server/wm/WindowContainer.java
index dab02de..e7b4e83 100644
--- a/services/core/java/com/android/server/wm/WindowContainer.java
+++ b/services/core/java/com/android/server/wm/WindowContainer.java
@@ -1196,6 +1196,23 @@
return false;
}
+ boolean isExitAnimationRunningSelfOrChild() {
+ if (!mTransitionController.isShellTransitionsEnabled()) {
+ return isAnimating(TRANSITION | CHILDREN, WindowState.EXIT_ANIMATING_TYPES);
+ }
+ if (mTransitionController.isCollecting(this)) {
+ return true;
+ }
+
+ for (int i = mChildren.size() - 1; i >= 0; --i) {
+ WindowContainer child = mChildren.get(i);
+ if (child.isExitAnimationRunningSelfOrChild()) {
+ return true;
+ }
+ }
+ return false;
+ }
+
void sendAppVisibilityToClients() {
for (int i = mChildren.size() - 1; i >= 0; --i) {
final WindowContainer wc = mChildren.get(i);
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index 6718235..43e84ae 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -89,7 +89,6 @@
import static android.view.WindowManager.TRANSIT_NONE;
import static android.view.WindowManager.TRANSIT_RELAUNCH;
import static android.view.WindowManagerGlobal.ADD_OKAY;
-import static android.view.WindowManagerGlobal.RELAYOUT_RES_BLAST_SYNC;
import static android.view.WindowManagerGlobal.RELAYOUT_RES_SURFACE_CHANGED;
import static android.view.WindowManagerPolicyConstants.NAV_BAR_INVALID;
import static android.view.WindowManagerPolicyConstants.TYPE_LAYER_MULTIPLIER;
@@ -119,7 +118,6 @@
import static com.android.server.wm.RootWindowContainer.MATCH_ATTACHED_TASK_OR_RECENT_TASKS;
import static com.android.server.wm.SurfaceAnimator.ANIMATION_TYPE_ALL;
import static com.android.server.wm.WindowContainer.AnimationFlags.CHILDREN;
-import static com.android.server.wm.WindowContainer.AnimationFlags.PARENTS;
import static com.android.server.wm.WindowContainer.AnimationFlags.TRANSITION;
import static com.android.server.wm.WindowManagerDebugConfig.DEBUG;
import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_DISPLAY;
@@ -745,6 +743,9 @@
private final DisplayHashController mDisplayHashController;
+ volatile float mMaximumObscuringOpacityForTouch =
+ InputManager.DEFAULT_MAXIMUM_OBSCURING_OPACITY_FOR_TOUCH;
+
@VisibleForTesting
final WindowContextListenerController mWindowContextListenerController =
new WindowContextListenerController();
@@ -782,6 +783,8 @@
DEVELOPMENT_RENDER_SHADOWS_IN_COMPOSITOR);
private final Uri mDisplaySettingsPathUri = Settings.Global.getUriFor(
DEVELOPMENT_WM_DISPLAY_SETTINGS_PATH);
+ private final Uri mMaximumObscuringOpacityForTouchUri = Settings.Global.getUriFor(
+ Settings.Global.MAXIMUM_OBSCURING_OPACITY_FOR_TOUCH);
public SettingsObserver() {
super(new Handler());
@@ -806,6 +809,8 @@
UserHandle.USER_ALL);
resolver.registerContentObserver(mDisplaySettingsPathUri, false, this,
UserHandle.USER_ALL);
+ resolver.registerContentObserver(mMaximumObscuringOpacityForTouchUri, false, this,
+ UserHandle.USER_ALL);
}
@Override
@@ -849,6 +854,11 @@
return;
}
+ if (mMaximumObscuringOpacityForTouchUri.equals(uri)) {
+ updateMaximumObscuringOpacityForTouch();
+ return;
+ }
+
@UpdateAnimationScaleMode
final int mode;
if (mWindowAnimationScaleUri.equals(uri)) {
@@ -868,6 +878,14 @@
void loadSettings() {
updateSystemUiSettings(false /* handleChange */);
updatePointerLocation();
+ updateMaximumObscuringOpacityForTouch();
+ }
+
+ void updateMaximumObscuringOpacityForTouch() {
+ ContentResolver resolver = mContext.getContentResolver();
+ mMaximumObscuringOpacityForTouch = Settings.Global.getFloat(resolver,
+ Settings.Global.MAXIMUM_OBSCURING_OPACITY_FOR_TOUCH,
+ InputManager.DEFAULT_MAXIMUM_OBSCURING_OPACITY_FOR_TOUCH);
}
void updateSystemUiSettings(boolean handleChange) {
@@ -2138,6 +2156,7 @@
w.mGivenTouchableRegion.scale(w.mGlobalScale);
}
w.setDisplayLayoutNeeded();
+ w.updateSourceFrame(w.getFrame());
mWindowPlacerLocked.performSurfacePlacement();
w.getDisplayContent().getInputMonitor().updateInputWindowsLw(true);
@@ -2192,7 +2211,7 @@
int requestedWidth, int requestedHeight, int viewVisibility, int flags,
ClientWindowFrames outFrames, MergedConfiguration mergedConfiguration,
SurfaceControl outSurfaceControl, InsetsState outInsetsState,
- InsetsSourceControl[] outActiveControls) {
+ InsetsSourceControl[] outActiveControls, Bundle outSyncIdBundle) {
Arrays.fill(outActiveControls, null);
int result = 0;
boolean configChanged;
@@ -2483,19 +2502,20 @@
ProtoLog.v(WM_DEBUG_FOCUS, "Relayout of %s: focusMayChange=%b",
win, focusMayChange);
- result |= mInTouchMode ? WindowManagerGlobal.RELAYOUT_RES_IN_TOUCH_MODE : 0;
-
if (DEBUG_LAYOUT) {
Slog.v(TAG_WM, "Relayout complete " + win + ": outFrames=" + outFrames);
}
win.mInRelayout = false;
if (mUseBLASTSync && win.useBLASTSync() && viewVisibility != View.GONE
- && win.mNextRelayoutUseSync) {
+ && (win.mSyncSeqId > win.mLastSeqIdSentToRelayout)) {
win.prepareDrawHandlers();
win.markRedrawForSyncReported();
- win.mNextRelayoutUseSync = false;
- result |= RELAYOUT_RES_BLAST_SYNC;
+
+ win.mLastSeqIdSentToRelayout = win.mSyncSeqId;
+ outSyncIdBundle.putInt("seqid", win.mSyncSeqId);
+ } else {
+ outSyncIdBundle.putInt("seqid", -1);
}
if (configChanged) {
@@ -2543,8 +2563,7 @@
if (win.isWinVisibleLw() && winAnimator.applyAnimationLocked(transit, false)) {
focusMayChange = true;
win.mAnimatingExit = true;
- } else if (win.mDisplayContent.okToAnimate() && win.isAnimating(TRANSITION | PARENTS,
- WindowState.EXIT_ANIMATING_TYPES)) {
+ } else if (win.mDisplayContent.okToAnimate() && win.isExitAnimationRunningSelfOrParent()) {
// Currently in a hide animation... turn this into
// an exit.
win.mAnimatingExit = true;
@@ -2617,7 +2636,7 @@
}
void finishDrawingWindow(Session session, IWindow client,
- @Nullable SurfaceControl.Transaction postDrawTransaction) {
+ @Nullable SurfaceControl.Transaction postDrawTransaction, int seqId) {
if (postDrawTransaction != null) {
postDrawTransaction.sanitize();
}
@@ -2628,7 +2647,7 @@
WindowState win = windowForClientLocked(session, client, false);
ProtoLog.d(WM_DEBUG_ADD_REMOVE, "finishDrawingWindow: %s mDrawState=%s",
win, (win != null ? win.mWinAnimator.drawStateToString() : "null"));
- if (win != null && win.finishDrawing(postDrawTransaction)) {
+ if (win != null && win.finishDrawing(postDrawTransaction, seqId)) {
if (win.hasWallpaper()) {
win.getDisplayContent().pendingLayoutChanges |=
WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER;
@@ -3262,7 +3281,7 @@
mContext.enforceCallingOrSelfPermission(
Manifest.permission.SUBSCRIBE_TO_KEYGUARD_LOCKED_STATE,
Manifest.permission.SUBSCRIBE_TO_KEYGUARD_LOCKED_STATE
- + " permission required to read keyguard visibility");
+ + " permission required to subscribe to keyguard locked state changes");
}
private void dispatchKeyguardLockedState() {
diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java
index db687f6..0ee8820 100644
--- a/services/core/java/com/android/server/wm/WindowState.java
+++ b/services/core/java/com/android/server/wm/WindowState.java
@@ -134,6 +134,7 @@
import static com.android.server.wm.SurfaceAnimator.ANIMATION_TYPE_RECENTS;
import static com.android.server.wm.SurfaceAnimator.ANIMATION_TYPE_STARTING_REVEAL;
import static com.android.server.wm.SurfaceAnimator.ANIMATION_TYPE_WINDOW_ANIMATION;
+import static com.android.server.wm.WindowContainer.AnimationFlags.CHILDREN;
import static com.android.server.wm.WindowContainer.AnimationFlags.PARENTS;
import static com.android.server.wm.WindowContainer.AnimationFlags.TRANSITION;
import static com.android.server.wm.WindowContainerChildProto.WINDOW;
@@ -141,7 +142,6 @@
import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_ANIM;
import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_CONFIGURATION;
import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_INPUT_METHOD;
-import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_LAYOUT;
import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_POWER;
import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_STARTING_WINDOW_VERBOSE;
import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_VISIBILITY;
@@ -368,7 +368,8 @@
private boolean mDragResizingChangeReported = true;
private int mResizeMode;
private boolean mRedrawForSyncReported;
- boolean mNextRelayoutUseSync;
+ int mSyncSeqId = 0;
+ int mLastSeqIdSentToRelayout = 0;
/**
* {@code true} when the client was still drawing for sync when the sync-set was finished or
@@ -859,6 +860,7 @@
/**
* @see #setOnBackInvokedCallback(IOnBackInvokedCallback)
*/
+ // TODO(b/224856664): Consolidate application and system callback into one.
private IOnBackInvokedCallback mApplicationOnBackInvokedCallback;
private IOnBackInvokedCallback mSystemOnBackInvokedCallback;
@@ -1124,7 +1126,9 @@
this, onBackInvokedCallback);
if (priority >= 0) {
mApplicationOnBackInvokedCallback = onBackInvokedCallback;
+ mSystemOnBackInvokedCallback = null;
} else {
+ mApplicationOnBackInvokedCallback = null;
mSystemOnBackInvokedCallback = onBackInvokedCallback;
}
}
@@ -1393,15 +1397,19 @@
}
// TODO(b/161810301): Make the frame be passed from the client side.
- void setFrame() {
- // TODO(b/161810301): Set the window frame here. We don't have to do it now because
- // DisplayPolicy has already done it for the window.
-
+ void setFrames(ClientWindowFrames clientWindowFrames) {
mHaveFrame = true;
final WindowFrames windowFrames = mWindowFrames;
+ mTmpRect.set(windowFrames.mParentFrame);
+ windowFrames.mDisplayFrame.set(clientWindowFrames.displayFrame);
+ windowFrames.mParentFrame.set(clientWindowFrames.parentFrame);
+ windowFrames.mFrame.set(clientWindowFrames.frame);
+ windowFrames.setParentFrameWasClippedByDisplayCutout(
+ clientWindowFrames.isParentFrameClippedByDisplayCutout);
- if (mRequestedWidth != mLastRequestedWidth || mRequestedHeight != mLastRequestedHeight) {
+ if (mRequestedWidth != mLastRequestedWidth || mRequestedHeight != mLastRequestedHeight
+ || !mTmpRect.equals(windowFrames.mParentFrame)) {
mLastRequestedWidth = mRequestedWidth;
mLastRequestedHeight = mRequestedHeight;
windowFrames.setContentChanged(true);
@@ -1430,16 +1438,6 @@
windowFrames.mRelFrame.offsetTo(windowFrames.mFrame.left - parentLeft,
windowFrames.mFrame.top - parentTop);
- if (DEBUG_LAYOUT || DEBUG) {
- final int pw = windowFrames.mParentFrame.width();
- final int ph = windowFrames.mParentFrame.height();
- Slog.v(TAG, "Resolving (mRequestedWidth="
- + mRequestedWidth + ", mRequestedheight="
- + mRequestedHeight + ") to" + " (pw=" + pw + ", ph=" + ph
- + "): frame=" + windowFrames.mFrame.toShortString()
- + " " + mAttrs.getTitle());
- }
-
if (mAttrs.type == TYPE_DOCK_DIVIDER) {
if (!windowFrames.mFrame.equals(windowFrames.mLastFrame)) {
mMovedByResize = true;
@@ -1454,9 +1452,19 @@
}
}
- // Update the source frame to provide insets to other windows during layout.
- if (mControllableInsetProvider != null) {
- mControllableInsetProvider.updateSourceFrame();
+ updateSourceFrame(windowFrames.mFrame);
+ }
+
+ void updateSourceFrame(Rect winFrame) {
+ if (mGivenInsetsPending) {
+ // The given insets are pending, and they are not reliable for now. The source frame
+ // should be updated after the new given insets are sent to window manager.
+ return;
+ }
+ final SparseArray<InsetsSource> providedSources = getProvidedInsetsSources();
+ final InsetsStateController controller = getDisplayContent().getInsetsStateController();
+ for (int i = providedSources.size() - 1; i >= 0; i--) {
+ controller.getSourceProvider(providedSources.keyAt(i)).updateSourceFrame(winFrame);
}
}
@@ -2610,8 +2618,7 @@
mWmService.mAccessibilityController.onWindowTransition(this, transit);
}
}
- final boolean isAnimating = mAnimatingExit
- || isAnimating(TRANSITION | PARENTS, EXIT_ANIMATING_TYPES);
+ final boolean isAnimating = mAnimatingExit || isExitAnimationRunningSelfOrParent();
final boolean lastWindowIsStartingWindow = startingWindow && mActivityRecord != null
&& mActivityRecord.isLastWindow(this);
// We delay the removal of a window if it has a showing surface that can be used to run
@@ -3946,7 +3953,7 @@
try {
mClient.resized(mClientWindowFrames, reportDraw, mLastReportedConfiguration,
- forceRelayout, alwaysConsumeSystemBars, displayId);
+ forceRelayout, alwaysConsumeSystemBars, displayId, Integer.MAX_VALUE);
if (drawPending && reportOrientation && mOrientationChanging) {
mOrientationChangeRedrawRequestTime = SystemClock.elapsedRealtime();
ProtoLog.v(WM_DEBUG_ORIENTATION,
@@ -4977,6 +4984,15 @@
return false;
}
+ boolean isExitAnimationRunningSelfOrParent() {
+ return inAppOrRecentsTransition()
+ || isAnimating(0 /* flags */, ANIMATION_TYPE_WINDOW_ANIMATION);
+ }
+
+ boolean isExitAnimationRunningSelfOrChild() {
+ return isAnimating(CHILDREN, ANIMATION_TYPE_WINDOW_ANIMATION);
+ }
+
private boolean shouldFinishAnimatingExit() {
// Exit animation might be applied soon.
if (inTransition()) {
@@ -4988,7 +5004,7 @@
return true;
}
// Exit animation is running.
- if (isAnimating(TRANSITION | PARENTS, EXIT_ANIMATING_TYPES)) {
+ if (isExitAnimationRunningSelfOrParent()) {
ProtoLog.d(WM_DEBUG_APP_TRANSITIONS, "shouldWaitAnimatingExit: isAnimating: %s",
this);
return false;
@@ -5081,7 +5097,7 @@
@Override
boolean handleCompleteDeferredRemoval() {
- if (mRemoveOnExit && !isSelfAnimating(0 /* flags */, EXIT_ANIMATING_TYPES)) {
+ if (mRemoveOnExit && !isSelfAnimating(0 /* flags */, ANIMATION_TYPE_WINDOW_ANIMATION)) {
mRemoveOnExit = false;
removeImmediately();
}
@@ -5914,7 +5930,7 @@
// to draw even if the children draw first or don't need to sync, so we start
// in WAITING state rather than READY.
mSyncState = SYNC_STATE_WAITING_FOR_DRAW;
- mNextRelayoutUseSync = true;
+ mSyncSeqId++;
requestRedrawForSync();
return true;
}
@@ -5938,7 +5954,7 @@
super.finishSync(outMergedTransaction, cancel);
}
- boolean finishDrawing(SurfaceControl.Transaction postDrawTransaction) {
+ boolean finishDrawing(SurfaceControl.Transaction postDrawTransaction, int syncSeqId) {
if (mOrientationChangeRedrawRequestTime > 0) {
final long duration =
SystemClock.elapsedRealtime() - mOrientationChangeRedrawRequestTime;
@@ -5985,7 +6001,7 @@
void immediatelyNotifyBlastSync() {
prepareDrawHandlers();
- finishDrawing(null);
+ finishDrawing(null, Integer.MAX_VALUE);
mWmService.mH.removeMessages(WINDOW_STATE_BLAST_SYNC_TIMEOUT, this);
if (!useBLASTSync()) return;
}
@@ -6057,7 +6073,7 @@
*/
void applyWithNextDraw(Consumer<SurfaceControl.Transaction> consumer) {
mPendingDrawHandlers.add(consumer);
- mNextRelayoutUseSync = true;
+ mSyncSeqId++;
requestRedrawForSync();
mWmService.mH.sendNewMessageDelayed(WINDOW_STATE_BLAST_SYNC_TIMEOUT, this,
diff --git a/services/core/jni/gnss/MeasurementCorrections.cpp b/services/core/jni/gnss/MeasurementCorrections.cpp
index 8a3d84c..07d0a45 100644
--- a/services/core/jni/gnss/MeasurementCorrections.cpp
+++ b/services/core/jni/gnss/MeasurementCorrections.cpp
@@ -44,6 +44,7 @@
using ReflectingPlane_V1_0 =
android::hardware::gnss::measurement_corrections::V1_0::ReflectingPlane;
using ReflectingPlane_Aidl = android::hardware::gnss::measurement_corrections::ReflectingPlane;
+using ExcessPathInfo = SingleSatCorrection_Aidl::ExcessPathInfo;
using GnssConstellationType_V1_0 = android::hardware::gnss::V1_0::GnssConstellationType;
using GnssConstellationType_V2_0 = android::hardware::gnss::V2_0::GnssConstellationType;
using GnssConstellationType_Aidl = android::hardware::gnss::GnssConstellationType;
@@ -62,7 +63,7 @@
jmethodID method_correctionsGetEnvironmentBearingDegrees;
jmethodID method_correctionsGetEnvironmentBearingUncertaintyDegrees;
jmethodID method_listSize;
-jmethodID method_correctionListGet;
+jmethodID method_listGet;
jmethodID method_correctionSatFlags;
jmethodID method_correctionSatConstType;
jmethodID method_correctionSatId;
@@ -71,10 +72,17 @@
jmethodID method_correctionSatEpl;
jmethodID method_correctionSatEplUnc;
jmethodID method_correctionSatRefPlane;
+jmethodID method_correctionSatAttenuation;
+jmethodID method_correctionSatExcessPathInfoList;
jmethodID method_correctionPlaneLatDeg;
jmethodID method_correctionPlaneLngDeg;
jmethodID method_correctionPlaneAltDeg;
jmethodID method_correctionPlaneAzimDeg;
+jmethodID method_excessPathInfoFlags;
+jmethodID method_excessPathInfoEpl;
+jmethodID method_excessPathInfoEplUnc;
+jmethodID method_excessPathInfoRefPlane;
+jmethodID method_excessPathInfoAttenuation;
} // anonymous namespace
void MeasurementCorrections_class_init_once(JNIEnv* env, jclass clazz) {
@@ -103,7 +111,7 @@
jclass corrListClass = env->FindClass("java/util/List");
method_listSize = env->GetMethodID(corrListClass, "size", "()I");
- method_correctionListGet = env->GetMethodID(corrListClass, "get", "(I)Ljava/lang/Object;");
+ method_listGet = env->GetMethodID(corrListClass, "get", "(I)Ljava/lang/Object;");
jclass singleSatCorrClass = env->FindClass("android/location/GnssSingleSatCorrection");
method_correctionSatFlags =
@@ -121,12 +129,27 @@
env->GetMethodID(singleSatCorrClass, "getExcessPathLengthUncertaintyMeters", "()F");
method_correctionSatRefPlane = env->GetMethodID(singleSatCorrClass, "getReflectingPlane",
"()Landroid/location/GnssReflectingPlane;");
+ method_correctionSatAttenuation =
+ env->GetMethodID(singleSatCorrClass, "getCombinedAttenuationDb", "()F");
+ method_correctionSatExcessPathInfoList =
+ env->GetMethodID(singleSatCorrClass, "getGnssExcessPathInfoList", "()Ljava/util/List;");
jclass refPlaneClass = env->FindClass("android/location/GnssReflectingPlane");
method_correctionPlaneLatDeg = env->GetMethodID(refPlaneClass, "getLatitudeDegrees", "()D");
method_correctionPlaneLngDeg = env->GetMethodID(refPlaneClass, "getLongitudeDegrees", "()D");
method_correctionPlaneAltDeg = env->GetMethodID(refPlaneClass, "getAltitudeMeters", "()D");
method_correctionPlaneAzimDeg = env->GetMethodID(refPlaneClass, "getAzimuthDegrees", "()D");
+
+ jclass excessPathInfoClass = env->FindClass("android/location/GnssExcessPathInfo");
+ method_excessPathInfoFlags = env->GetMethodID(excessPathInfoClass, "getFlags", "()I");
+ method_excessPathInfoEpl =
+ env->GetMethodID(excessPathInfoClass, "getExcessPathLengthMeters", "()F");
+ method_excessPathInfoEplUnc =
+ env->GetMethodID(excessPathInfoClass, "getExcessPathLengthUncertaintyMeters", "()F");
+ method_excessPathInfoRefPlane = env->GetMethodID(excessPathInfoClass, "getReflectingPlane",
+ "()Landroid/location/GnssReflectingPlane;");
+ method_excessPathInfoAttenuation =
+ env->GetMethodID(excessPathInfoClass, "getAttenuationDb", "()F");
}
template <>
@@ -324,7 +347,8 @@
SingleSatCorrection_V1_0
MeasurementCorrectionsUtil::getSingleSatCorrection_1_0_withoutConstellation(
JNIEnv* env, jobject singleSatCorrectionObj) {
- jint correctionFlags = env->CallIntMethod(singleSatCorrectionObj, method_correctionSatFlags);
+ uint16_t corrFlags = static_cast<uint16_t>(
+ env->CallIntMethod(singleSatCorrectionObj, method_correctionSatFlags));
jint satId = env->CallIntMethod(singleSatCorrectionObj, method_correctionSatId);
jfloat carrierFreqHz =
env->CallFloatMethod(singleSatCorrectionObj, method_correctionSatCarrierFreq);
@@ -332,14 +356,16 @@
env->CallFloatMethod(singleSatCorrectionObj, method_correctionSatIsLosProb);
jfloat eplMeters = env->CallFloatMethod(singleSatCorrectionObj, method_correctionSatEpl);
jfloat eplUncMeters = env->CallFloatMethod(singleSatCorrectionObj, method_correctionSatEplUnc);
- uint16_t corrFlags = static_cast<uint16_t>(correctionFlags);
ReflectingPlane_V1_0 reflectingPlane;
- if ((corrFlags & GnssSingleSatCorrectionFlags_V1_0::HAS_REFLECTING_PLANE) != 0)
- MeasurementCorrectionsUtil::getReflectingPlane<ReflectingPlane_V1_0>(env,
- singleSatCorrectionObj,
+ if ((corrFlags & GnssSingleSatCorrectionFlags_V1_0::HAS_REFLECTING_PLANE) != 0) {
+ jobject reflectingPlaneObj =
+ env->CallObjectMethod(singleSatCorrectionObj, method_correctionSatRefPlane);
+ MeasurementCorrectionsUtil::setReflectingPlane<ReflectingPlane_V1_0>(env,
+ reflectingPlaneObj,
reflectingPlane);
-
+ env->DeleteLocalRef(reflectingPlaneObj);
+ }
SingleSatCorrection_V1_0 singleSatCorrection = {
.singleSatCorrectionFlags = corrFlags,
.svid = static_cast<uint16_t>(satId),
@@ -349,13 +375,14 @@
.excessPathLengthUncertaintyMeters = eplUncMeters,
.reflectingPlane = reflectingPlane,
};
-
return singleSatCorrection;
}
SingleSatCorrection_Aidl MeasurementCorrectionsUtil::getSingleSatCorrection_Aidl(
JNIEnv* env, jobject singleSatCorrectionObj) {
- jint correctionFlags = env->CallIntMethod(singleSatCorrectionObj, method_correctionSatFlags);
+ int32_t corrFlags = static_cast<int32_t>(
+ env->CallIntMethod(singleSatCorrectionObj, method_correctionSatFlags));
+ jint constType = env->CallIntMethod(singleSatCorrectionObj, method_correctionSatConstType);
jint satId = env->CallIntMethod(singleSatCorrectionObj, method_correctionSatId);
jfloat carrierFreqHz =
env->CallFloatMethod(singleSatCorrectionObj, method_correctionSatCarrierFreq);
@@ -363,15 +390,10 @@
env->CallFloatMethod(singleSatCorrectionObj, method_correctionSatIsLosProb);
jfloat eplMeters = env->CallFloatMethod(singleSatCorrectionObj, method_correctionSatEpl);
jfloat eplUncMeters = env->CallFloatMethod(singleSatCorrectionObj, method_correctionSatEplUnc);
- int32_t corrFlags = static_cast<int32_t>(correctionFlags);
-
- ReflectingPlane_Aidl reflectingPlane;
- if ((corrFlags & SingleSatCorrection_Aidl::SINGLE_SAT_CORRECTION_HAS_REFLECTING_PLANE) != 0)
- MeasurementCorrectionsUtil::getReflectingPlane<ReflectingPlane_Aidl>(env,
- singleSatCorrectionObj,
- reflectingPlane);
-
- jint constType = env->CallIntMethod(singleSatCorrectionObj, method_correctionSatConstType);
+ jfloat attenuationDb =
+ env->CallFloatMethod(singleSatCorrectionObj, method_correctionSatAttenuation);
+ std::vector<ExcessPathInfo> excessPathInfos =
+ MeasurementCorrectionsUtil::getExcessPathInfoList(env, singleSatCorrectionObj);
SingleSatCorrection_Aidl singleSatCorrection;
singleSatCorrection.singleSatCorrectionFlags = corrFlags;
@@ -379,9 +401,10 @@
singleSatCorrection.svid = static_cast<int32_t>(satId);
singleSatCorrection.carrierFrequencyHz = carrierFreqHz;
singleSatCorrection.probSatIsLos = probSatIsLos;
- singleSatCorrection.excessPathLengthMeters = eplMeters;
- singleSatCorrection.excessPathLengthUncertaintyMeters = eplUncMeters;
- singleSatCorrection.reflectingPlane = reflectingPlane;
+ singleSatCorrection.combinedExcessPathLengthMeters = eplMeters;
+ singleSatCorrection.combinedExcessPathLengthUncertaintyMeters = eplUncMeters;
+ singleSatCorrection.combinedAttenuationDb = attenuationDb;
+ singleSatCorrection.excessPathInfos = excessPathInfos;
return singleSatCorrection;
}
@@ -391,8 +414,7 @@
hardware::hidl_vec<SingleSatCorrection_V1_0>& list) {
for (uint16_t i = 0; i < list.size(); ++i) {
jobject singleSatCorrectionObj =
- env->CallObjectMethod(singleSatCorrectionList, method_correctionListGet, i);
-
+ env->CallObjectMethod(singleSatCorrectionList, method_listGet, i);
SingleSatCorrection_V1_0 singleSatCorrection =
getSingleSatCorrection_1_0_withoutConstellation(env, singleSatCorrectionObj);
@@ -410,7 +432,7 @@
hardware::hidl_vec<SingleSatCorrection_V1_1>& list) {
for (uint16_t i = 0; i < list.size(); ++i) {
jobject singleSatCorrectionObj =
- env->CallObjectMethod(singleSatCorrectionList, method_correctionListGet, i);
+ env->CallObjectMethod(singleSatCorrectionList, method_listGet, i);
SingleSatCorrection_V1_0 singleSatCorrection_1_0 =
getSingleSatCorrection_1_0_withoutConstellation(env, singleSatCorrectionObj);
@@ -431,7 +453,7 @@
JNIEnv* env, jobject singleSatCorrectionList, std::vector<SingleSatCorrection_Aidl>& list) {
for (uint16_t i = 0; i < list.size(); ++i) {
jobject singleSatCorrectionObj =
- env->CallObjectMethod(singleSatCorrectionList, method_correctionListGet, i);
+ env->CallObjectMethod(singleSatCorrectionList, method_listGet, i);
SingleSatCorrection_Aidl singleSatCorrection_Aidl =
getSingleSatCorrection_Aidl(env, singleSatCorrectionObj);
@@ -441,4 +463,63 @@
}
}
+template <>
+void MeasurementCorrectionsUtil::setReflectingPlaneAzimuthDegrees<ReflectingPlane_V1_0>(
+ ReflectingPlane_V1_0& reflectingPlane, double azimuthDegreeRefPlane) {
+ reflectingPlane.azimuthDegrees = azimuthDegreeRefPlane;
+}
+
+template <>
+void MeasurementCorrectionsUtil::setReflectingPlaneAzimuthDegrees<ReflectingPlane_Aidl>(
+ ReflectingPlane_Aidl& reflectingPlane, double azimuthDegreeRefPlane) {
+ reflectingPlane.reflectingPlaneAzimuthDegrees = azimuthDegreeRefPlane;
+}
+
+std::vector<ExcessPathInfo> MeasurementCorrectionsUtil::getExcessPathInfoList(
+ JNIEnv* env, jobject singleSatCorrectionObj) {
+ jobject excessPathInfoListObj =
+ env->CallObjectMethod(singleSatCorrectionObj, method_correctionSatExcessPathInfoList);
+
+ int len = env->CallIntMethod(excessPathInfoListObj, method_listSize);
+ std::vector<ExcessPathInfo> list(len);
+ for (int i = 0; i < len; ++i) {
+ jobject excessPathInfoObj = env->CallObjectMethod(excessPathInfoListObj, method_listGet, i);
+ list[i] = getExcessPathInfo(env, excessPathInfoObj);
+ env->DeleteLocalRef(excessPathInfoObj);
+ }
+ env->DeleteLocalRef(excessPathInfoListObj);
+ return list;
+}
+
+ExcessPathInfo MeasurementCorrectionsUtil::getExcessPathInfo(JNIEnv* env,
+ jobject excessPathInfoObj) {
+ ExcessPathInfo excessPathInfo;
+ jint flags = env->CallIntMethod(excessPathInfoObj, method_excessPathInfoFlags);
+ excessPathInfo.excessPathInfoFlags = flags;
+ if ((flags & ExcessPathInfo::EXCESS_PATH_INFO_HAS_EXCESS_PATH_LENGTH) != 0) {
+ jfloat epl = env->CallFloatMethod(excessPathInfoObj, method_excessPathInfoEpl);
+ excessPathInfo.excessPathLengthMeters = epl;
+ }
+ if ((flags & ExcessPathInfo::EXCESS_PATH_INFO_HAS_EXCESS_PATH_LENGTH_UNC) != 0) {
+ jfloat eplUnc = env->CallFloatMethod(excessPathInfoObj, method_excessPathInfoEplUnc);
+ excessPathInfo.excessPathLengthUncertaintyMeters = eplUnc;
+ }
+ if ((flags & ExcessPathInfo::EXCESS_PATH_INFO_HAS_REFLECTING_PLANE) != 0) {
+ ReflectingPlane_Aidl reflectingPlane;
+ jobject reflectingPlaneObj =
+ env->CallObjectMethod(excessPathInfoObj, method_excessPathInfoRefPlane);
+ MeasurementCorrectionsUtil::setReflectingPlane<ReflectingPlane_Aidl>(env,
+ reflectingPlaneObj,
+ reflectingPlane);
+ env->DeleteLocalRef(reflectingPlaneObj);
+ excessPathInfo.reflectingPlane = reflectingPlane;
+ }
+ if ((flags & ExcessPathInfo::EXCESS_PATH_INFO_HAS_ATTENUATION) != 0) {
+ jfloat attenuation =
+ env->CallFloatMethod(excessPathInfoObj, method_excessPathInfoAttenuation);
+ excessPathInfo.attenuationDb = attenuation;
+ }
+ return excessPathInfo;
+}
+
} // namespace android::gnss
diff --git a/services/core/jni/gnss/MeasurementCorrections.h b/services/core/jni/gnss/MeasurementCorrections.h
index a2e6027..598ad48 100644
--- a/services/core/jni/gnss/MeasurementCorrections.h
+++ b/services/core/jni/gnss/MeasurementCorrections.h
@@ -43,7 +43,7 @@
extern jmethodID method_correctionsGetEnvironmentBearingDegrees;
extern jmethodID method_correctionsGetEnvironmentBearingUncertaintyDegrees;
extern jmethodID method_listSize;
-extern jmethodID method_correctionListGet;
+extern jmethodID method_listGet;
extern jmethodID method_correctionSatFlags;
extern jmethodID method_correctionSatConstType;
extern jmethodID method_correctionSatId;
@@ -52,6 +52,7 @@
extern jmethodID method_correctionSatEpl;
extern jmethodID method_correctionSatEplUnc;
extern jmethodID method_correctionSatRefPlane;
+extern jmethodID method_correctionSatExcessPathInfos;
extern jmethodID method_correctionPlaneLatDeg;
extern jmethodID method_correctionPlaneLngDeg;
extern jmethodID method_correctionPlaneAltDeg;
@@ -130,14 +131,20 @@
static bool translateMeasurementCorrections(JNIEnv* env, jobject correctionsObj,
T& corrections);
template <class T>
- static void getReflectingPlane(JNIEnv* env, jobject singleSatCorrectionObj, T& reflectingPlane);
+ static void setReflectingPlane(JNIEnv* env, jobject reflectingPlaneObj, T& reflectingPlane);
+ template <class T>
+ static void setReflectingPlaneAzimuthDegrees(T& reflectingPlane, double azimuthDegreeRefPlane);
+
+ static std::vector<
+ android::hardware::gnss::measurement_corrections::SingleSatCorrection::ExcessPathInfo>
+ getExcessPathInfoList(JNIEnv* env, jobject correctionsObj);
+ static android::hardware::gnss::measurement_corrections::SingleSatCorrection::ExcessPathInfo
+ getExcessPathInfo(JNIEnv* env, jobject correctionsObj);
};
template <class T>
-void MeasurementCorrectionsUtil::getReflectingPlane(JNIEnv* env, jobject singleSatCorrectionObj,
+void MeasurementCorrectionsUtil::setReflectingPlane(JNIEnv* env, jobject reflectingPlaneObj,
T& reflectingPlane) {
- jobject reflectingPlaneObj =
- env->CallObjectMethod(singleSatCorrectionObj, method_correctionSatRefPlane);
jdouble latitudeDegreesRefPlane =
env->CallDoubleMethod(reflectingPlaneObj, method_correctionPlaneLatDeg);
jdouble longitudeDegreesRefPlane =
@@ -149,8 +156,7 @@
reflectingPlane.latitudeDegrees = latitudeDegreesRefPlane;
reflectingPlane.longitudeDegrees = longitudeDegreesRefPlane;
reflectingPlane.altitudeMeters = altitudeDegreesRefPlane;
- reflectingPlane.azimuthDegrees = azimuthDegreeRefPlane;
- env->DeleteLocalRef(reflectingPlaneObj);
+ setReflectingPlaneAzimuthDegrees<T>(reflectingPlane, azimuthDegreeRefPlane);
}
} // namespace android::gnss
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/ActiveAdmin.java b/services/devicepolicy/java/com/android/server/devicepolicy/ActiveAdmin.java
index 2f5ab0b..48c4052 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/ActiveAdmin.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/ActiveAdmin.java
@@ -1227,5 +1227,12 @@
pw.print("mSsidDenylist=");
pw.println(mSsidDenylist);
+
+ if (mFactoryResetProtectionPolicy != null) {
+ pw.println("mFactoryResetProtectionPolicy:");
+ pw.increaseIndent();
+ mFactoryResetProtectionPolicy.dump(pw);
+ pw.decreaseIndent();
+ }
}
}
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/BaseIDevicePolicyManager.java b/services/devicepolicy/java/com/android/server/devicepolicy/BaseIDevicePolicyManager.java
index 200b120..edfd6ed 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/BaseIDevicePolicyManager.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/BaseIDevicePolicyManager.java
@@ -15,6 +15,7 @@
*/
package com.android.server.devicepolicy;
+import android.accounts.Account;
import android.annotation.NonNull;
import android.annotation.UserIdInt;
import android.app.admin.DevicePolicyDrawableResource;
@@ -138,6 +139,11 @@
return null;
}
+ public void finalizeWorkProfileProvisioning(
+ UserHandle managedProfileUser, Account migratedAccount) {
+
+ }
+
public void provisionFullyManagedDevice(
FullyManagedDeviceProvisioningParams provisioningParams, String callerPackage) {
}
@@ -171,7 +177,7 @@
public void setDrawables(@NonNull List<DevicePolicyDrawableResource> drawables){}
@Override
- public void resetDrawables(@NonNull String[] drawableIds){}
+ public void resetDrawables(@NonNull List<String> drawableIds){}
@Override
public ParcelableResource getDrawable(
@@ -183,10 +189,15 @@
public void setStrings(@NonNull List<DevicePolicyStringResource> strings){}
@Override
- public void resetStrings(String[] stringIds){}
+ public void resetStrings(@NonNull List<String> stringIds){}
@Override
public ParcelableResource getString(String stringId) {
return null;
}
+
+ @Override
+ public boolean shouldAllowBypassingDevicePolicyManagementRoleQualification() {
+ return false;
+ }
}
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DeviceManagementResourcesProvider.java b/services/devicepolicy/java/com/android/server/devicepolicy/DeviceManagementResourcesProvider.java
index e70c071..bf78c67 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/DeviceManagementResourcesProvider.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/DeviceManagementResourcesProvider.java
@@ -16,17 +16,14 @@
package com.android.server.devicepolicy;
-import static android.app.admin.DevicePolicyResources.Drawables.Source.UPDATABLE_DRAWABLE_SOURCES;
import static android.app.admin.DevicePolicyResources.Drawables.Style;
-import static android.app.admin.DevicePolicyResources.Drawables.Style.UPDATABLE_DRAWABLE_STYLES;
-import static android.app.admin.DevicePolicyResources.Drawables.UPDATABLE_DRAWABLE_IDS;
-import static android.app.admin.DevicePolicyResources.Strings.UPDATABLE_STRING_IDS;
import static java.util.Objects.requireNonNull;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.app.admin.DevicePolicyDrawableResource;
+import android.app.admin.DevicePolicyResources;
import android.app.admin.DevicePolicyResources.Drawables;
import android.app.admin.DevicePolicyStringResource;
import android.app.admin.ParcelableResource;
@@ -113,7 +110,7 @@
Objects.requireNonNull(drawableSource, "drawableSource must be provided.");
Objects.requireNonNull(resource, "ParcelableResource must be provided.");
- if (Drawables.Source.UNDEFINED.equals(drawableSource)) {
+ if (DevicePolicyResources.UNDEFINED.equals(drawableSource)) {
updated |= updateDrawable(drawableId, drawableStyle, resource);
} else {
updated |= updateDrawableForSource(drawableId, drawableSource, resource);
@@ -130,12 +127,6 @@
private boolean updateDrawable(
String drawableId, String drawableStyle, ParcelableResource updatableResource) {
- if (!UPDATABLE_DRAWABLE_IDS.contains(drawableId)) {
- Log.w(TAG, "Updating a resource for an unknown drawable id " + drawableId);
- }
- if (!UPDATABLE_DRAWABLE_STYLES.contains(drawableStyle)) {
- Log.w(TAG, "Updating a resource for an unknown style id " + drawableStyle);
- }
synchronized (mLock) {
if (!mUpdatedDrawablesForStyle.containsKey(drawableId)) {
mUpdatedDrawablesForStyle.put(drawableId, new HashMap<>());
@@ -153,12 +144,6 @@
// TODO(b/214576716): change this to respect style
private boolean updateDrawableForSource(
String drawableId, String drawableSource, ParcelableResource updatableResource) {
- if (!UPDATABLE_DRAWABLE_IDS.contains(drawableId)) {
- Log.w(TAG, "Updating a resource for an unknown drawable id " + drawableId);
- }
- if (!UPDATABLE_DRAWABLE_SOURCES.contains(drawableSource)) {
- Log.w(TAG, "Updating a resource for an unknown source id " + drawableSource);
- }
synchronized (mLock) {
if (!mUpdatedDrawablesForSource.containsKey(drawableId)) {
mUpdatedDrawablesForSource.put(drawableId, new HashMap<>());
@@ -176,11 +161,11 @@
/**
* Returns {@code false} if no resources were removed.
*/
- boolean removeDrawables(@NonNull String[] drawableIds) {
+ boolean removeDrawables(@NonNull List<String> drawableIds) {
synchronized (mLock) {
boolean removed = false;
- for (int i = 0; i < drawableIds.length; i++) {
- String drawableId = drawableIds[i];
+ for (int i = 0; i < drawableIds.size(); i++) {
+ String drawableId = drawableIds.get(i);
removed |= mUpdatedDrawablesForStyle.remove(drawableId) != null
|| mUpdatedDrawablesForSource.remove(drawableId) != null;
}
@@ -195,17 +180,6 @@
@Nullable
ParcelableResource getDrawable(
String drawableId, String drawableStyle, String drawableSource) {
- if (!UPDATABLE_DRAWABLE_IDS.contains(drawableId)) {
- Log.w(TAG, "Getting an updated resource for an unknown drawable id " + drawableId);
- }
- if (!UPDATABLE_DRAWABLE_STYLES.contains(drawableStyle)) {
- Log.w(TAG, "Getting an updated resource for an unknown drawable style "
- + drawableStyle);
- }
- if (!UPDATABLE_DRAWABLE_SOURCES.contains(drawableSource)) {
- Log.w(TAG, "Getting an updated resource for an unknown drawable Source "
- + drawableSource);
- }
if (mUpdatedDrawablesForSource.containsKey(drawableId)
&& mUpdatedDrawablesForSource.get(drawableId).containsKey(drawableSource)) {
return mUpdatedDrawablesForSource.get(drawableId).get(drawableSource);
@@ -217,10 +191,6 @@
if (mUpdatedDrawablesForStyle.get(drawableId).containsKey(drawableStyle)) {
return mUpdatedDrawablesForStyle.get(drawableId).get(drawableStyle);
}
-
- if (mUpdatedDrawablesForStyle.get(drawableId).containsKey(Style.DEFAULT)) {
- return mUpdatedDrawablesForStyle.get(drawableId).get(Style.DEFAULT);
- }
Log.d(TAG, "No updated drawable found for drawable id " + drawableId);
return null;
}
@@ -249,9 +219,6 @@
}
private boolean updateString(String stringId, ParcelableResource updatableResource) {
- if (!UPDATABLE_STRING_IDS.contains(stringId)) {
- Log.w(TAG, "Updating a resource for an unknown string id " + stringId);
- }
synchronized (mLock) {
ParcelableResource current = mUpdatedStrings.get(stringId);
if (updatableResource.equals(current)) {
@@ -265,11 +232,11 @@
/**
* Returns {@code false} if no resources were removed.
*/
- boolean removeStrings(@NonNull String[] stringIds) {
+ boolean removeStrings(@NonNull List<String> stringIds) {
synchronized (mLock) {
boolean removed = false;
- for (int i = 0; i < stringIds.length; i++) {
- String stringId = stringIds[i];
+ for (int i = 0; i < stringIds.size(); i++) {
+ String stringId = stringIds.get(i);
removed |= mUpdatedStrings.remove(stringId) != null;
}
if (!removed) {
@@ -282,10 +249,6 @@
@Nullable
ParcelableResource getString(String stringId) {
- if (!UPDATABLE_STRING_IDS.contains(stringId)) {
- Log.w(TAG, "Getting an updated resource for an unknown string id " + stringId);
- }
-
if (mUpdatedStrings.containsKey(stringId)) {
return mUpdatedStrings.get(stringId);
}
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
index 3d40f48..1288587 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
@@ -27,6 +27,7 @@
import static android.app.admin.DeviceAdminReceiver.EXTRA_TRANSFER_OWNERSHIP_ADMIN_EXTRAS_BUNDLE;
import static android.app.admin.DevicePolicyManager.ACTION_CHECK_POLICY_COMPLIANCE;
import static android.app.admin.DevicePolicyManager.ACTION_DEVICE_POLICY_RESOURCE_UPDATED;
+import static android.app.admin.DevicePolicyManager.ACTION_MANAGED_PROFILE_PROVISIONED;
import static android.app.admin.DevicePolicyManager.ACTION_PROVISION_MANAGED_DEVICE;
import static android.app.admin.DevicePolicyManager.ACTION_PROVISION_MANAGED_PROFILE;
import static android.app.admin.DevicePolicyManager.ACTION_PROVISION_MANAGED_USER;
@@ -45,6 +46,7 @@
import static android.app.admin.DevicePolicyManager.DEVICE_OWNER_TYPE_DEFAULT;
import static android.app.admin.DevicePolicyManager.DEVICE_OWNER_TYPE_FINANCED;
import static android.app.admin.DevicePolicyManager.ENCRYPTION_STATUS_ACTIVE_PER_USER;
+import static android.app.admin.DevicePolicyManager.EXTRA_PROVISIONING_ACCOUNT_TO_MIGRATE;
import static android.app.admin.DevicePolicyManager.EXTRA_RESOURCE_IDS;
import static android.app.admin.DevicePolicyManager.EXTRA_RESOURCE_TYPE;
import static android.app.admin.DevicePolicyManager.EXTRA_RESOURCE_TYPE_DRAWABLE;
@@ -2122,7 +2124,7 @@
+ "profile: %d", doUserId, poUserId);
Slogf.i(LOG_TAG, "Giving the PO additional power...");
- markProfileOwnerOnOrganizationOwnedDeviceUncheckedLocked(poAdminComponent, poUserId);
+ setProfileOwnerOnOrganizationOwnedDeviceUncheckedLocked(poAdminComponent, poUserId, true);
Slogf.i(LOG_TAG, "Migrating DO policies to PO...");
moveDoPoliciesToProfileParentAdminLocked(doAdmin, poAdmin.getParentActiveAdmin());
migratePersonalAppSuspensionLocked(doUserId, poUserId, poAdmin);
@@ -7030,10 +7032,10 @@
boolean calledByProfileOwnerOnOrgOwnedDevice, boolean calledOnParentInstance) {
DevicePolicyManager dpm = mContext.getSystemService(DevicePolicyManager.class);
return calledByProfileOwnerOnOrgOwnedDevice && !calledOnParentInstance
- ? dpm.getString(WORK_PROFILE_DELETED_ORG_OWNED_MESSAGE,
+ ? dpm.getResources().getString(WORK_PROFILE_DELETED_ORG_OWNED_MESSAGE,
() -> mContext.getString(
R.string.device_ownership_relinquished))
- : dpm.getString(WORK_PROFILE_DELETED_GENERIC_MESSAGE,
+ : dpm.getResources().getString(WORK_PROFILE_DELETED_GENERIC_MESSAGE,
() -> mContext.getString(
R.string.work_profile_deleted_description_dpm_wipe));
}
@@ -7132,7 +7134,7 @@
private String getWorkProfileDeletedTitle() {
DevicePolicyManager dpm = mContext.getSystemService(DevicePolicyManager.class);
- return dpm.getString(WORK_PROFILE_DELETED_TITLE,
+ return dpm.getResources().getString(WORK_PROFILE_DELETED_TITLE,
() -> mContext.getString(R.string.work_profile_deleted));
}
@@ -7448,7 +7450,7 @@
private String getFailedPasswordAttemptWipeMessage() {
DevicePolicyManager dpm = mContext.getSystemService(DevicePolicyManager.class);
- return dpm.getString(WORK_PROFILE_DELETED_FAILED_PASSWORD_ATTEMPTS_MESSAGE,
+ return dpm.getResources().getString(WORK_PROFILE_DELETED_FAILED_PASSWORD_ATTEMPTS_MESSAGE,
() -> mContext.getString(
R.string.work_profile_deleted_reason_maximum_password_failure));
}
@@ -12648,13 +12650,13 @@
private String getLocationChangedTitle() {
DevicePolicyManager dpm = mContext.getSystemService(DevicePolicyManager.class);
- return dpm.getString(LOCATION_CHANGED_TITLE,
+ return dpm.getResources().getString(LOCATION_CHANGED_TITLE,
() -> mContext.getString(R.string.location_changed_notification_title));
}
private String getLocationChangedText() {
DevicePolicyManager dpm = mContext.getSystemService(DevicePolicyManager.class);
- return dpm.getString(LOCATION_CHANGED_MESSAGE,
+ return dpm.getResources().getString(LOCATION_CHANGED_MESSAGE,
() -> mContext.getString(R.string.location_changed_notification_text));
}
@@ -13255,7 +13257,7 @@
return null;
}
DevicePolicyManager dpm = mContext.getSystemService(DevicePolicyManager.class);
- return dpm.getString(
+ return dpm.getResources().getString(
PRINTING_DISABLED_NAMED_ADMIN,
() -> getDefaultPrintingDisabledMsg(appLabel),
appLabel);
@@ -14772,7 +14774,8 @@
}
@Override
- public void markProfileOwnerOnOrganizationOwnedDevice(ComponentName who, int userId) {
+ public void setProfileOwnerOnOrganizationOwnedDevice(ComponentName who, int userId,
+ boolean isProfileOwnerOnOrganizationOwnedDevice) {
if (!mHasFeature) {
return;
}
@@ -14804,13 +14807,14 @@
// Grant access under lock.
synchronized (getLockObject()) {
- markProfileOwnerOnOrganizationOwnedDeviceUncheckedLocked(who, userId);
+ setProfileOwnerOnOrganizationOwnedDeviceUncheckedLocked(who, userId,
+ isProfileOwnerOnOrganizationOwnedDevice);
}
}
@GuardedBy("getLockObject()")
- private void markProfileOwnerOnOrganizationOwnedDeviceUncheckedLocked(
- ComponentName who, int userId) {
+ private void setProfileOwnerOnOrganizationOwnedDeviceUncheckedLocked(
+ ComponentName who, int userId, boolean isProfileOwnerOnOrganizationOwnedDevice) {
// Make sure that the user has a profile owner and that the specified
// component is the profile owner of that user.
if (!isProfileOwner(who, userId)) {
@@ -14819,7 +14823,8 @@
who.flattenToString(), userId));
}
- Slogf.i(LOG_TAG, "Marking %s as profile owner on organization-owned device for user %d",
+ Slogf.i(LOG_TAG, "%s %s as profile owner on organization-owned device for user %d",
+ isProfileOwnerOnOrganizationOwnedDevice ? "Marking" : "Unmarking",
who.flattenToString(), userId);
// First, set restriction on removing the profile.
@@ -14836,15 +14841,18 @@
+ " on user %d", parentUser.getIdentifier()));
}
- mUserManager.setUserRestriction(UserManager.DISALLOW_REMOVE_MANAGED_PROFILE, true,
+ mUserManager.setUserRestriction(UserManager.DISALLOW_REMOVE_MANAGED_PROFILE,
+ isProfileOwnerOnOrganizationOwnedDevice,
parentUser);
- mUserManager.setUserRestriction(UserManager.DISALLOW_ADD_USER, true,
+ mUserManager.setUserRestriction(UserManager.DISALLOW_ADD_USER,
+ isProfileOwnerOnOrganizationOwnedDevice,
parentUser);
});
- // markProfileOwnerOfOrganizationOwnedDevice will trigger writing of the profile owner
+ // setProfileOwnerOfOrganizationOwnedDevice will trigger writing of the profile owner
// data, no need to do it manually.
- mOwners.markProfileOwnerOfOrganizationOwnedDevice(userId);
+ mOwners.setProfileOwnerOfOrganizationOwnedDevice(userId,
+ isProfileOwnerOnOrganizationOwnedDevice);
}
private void pushMeteredDisabledPackagesLocked(int userId) {
@@ -15868,13 +15876,13 @@
private String getNetworkLoggingTitle() {
DevicePolicyManager dpm = mContext.getSystemService(DevicePolicyManager.class);
- return dpm.getString(NETWORK_LOGGING_TITLE,
+ return dpm.getResources().getString(NETWORK_LOGGING_TITLE,
() -> mContext.getString(R.string.network_logging_notification_title));
}
private String getNetworkLoggingText() {
DevicePolicyManager dpm = mContext.getSystemService(DevicePolicyManager.class);
- return dpm.getString(NETWORK_LOGGING_MESSAGE,
+ return dpm.getResources().getString(NETWORK_LOGGING_MESSAGE,
() -> mContext.getString(R.string.network_logging_notification_text));
}
@@ -17463,25 +17471,25 @@
private String getPersonalAppSuspensionButtonText() {
DevicePolicyManager dpm = mContext.getSystemService(DevicePolicyManager.class);
- return dpm.getString(PERSONAL_APP_SUSPENSION_TURN_ON_PROFILE,
+ return dpm.getResources().getString(PERSONAL_APP_SUSPENSION_TURN_ON_PROFILE,
() -> mContext.getString(R.string.personal_apps_suspended_turn_profile_on));
}
private String getPersonalAppSuspensionTitle() {
DevicePolicyManager dpm = mContext.getSystemService(DevicePolicyManager.class);
- return dpm.getString(PERSONAL_APP_SUSPENSION_TITLE,
+ return dpm.getResources().getString(PERSONAL_APP_SUSPENSION_TITLE,
() -> mContext.getString(R.string.personal_apps_suspension_title));
}
private String getPersonalAppSuspensionText() {
DevicePolicyManager dpm = mContext.getSystemService(DevicePolicyManager.class);
- return dpm.getString(PERSONAL_APP_SUSPENSION_TITLE,
+ return dpm.getResources().getString(PERSONAL_APP_SUSPENSION_TITLE,
() -> mContext.getString(R.string.personal_apps_suspension_text));
}
private String getPersonalAppSuspensionSoonText(String date, String time, int maxDays) {
DevicePolicyManager dpm = mContext.getSystemService(DevicePolicyManager.class);
- return dpm.getString(PERSONAL_APP_SUSPENSION_TITLE,
+ return dpm.getResources().getString(PERSONAL_APP_SUSPENSION_TITLE,
() -> mContext.getString(
R.string.personal_apps_suspension_soon_text, date, time, maxDays),
date, time, maxDays);
@@ -17489,7 +17497,7 @@
private String getWorkProfileContentDescription() {
DevicePolicyManager dpm = mContext.getSystemService(DevicePolicyManager.class);
- return dpm.getString(NOTIFICATION_WORK_PROFILE_CONTENT_DESCRIPTION,
+ return dpm.getResources().getString(NOTIFICATION_WORK_PROFILE_CONTENT_DESCRIPTION,
() -> mContext.getString(R.string.notification_work_profile_content_description));
}
@@ -17781,7 +17789,8 @@
if (provisioningParams.isOrganizationOwnedProvisioning()) {
synchronized (getLockObject()) {
- markProfileOwnerOnOrganizationOwnedDeviceUncheckedLocked(admin, userInfo.id);
+ setProfileOwnerOnOrganizationOwnedDeviceUncheckedLocked(admin, userInfo.id,
+ true);
}
}
@@ -17808,6 +17817,35 @@
}
}
+ @Override
+ public void finalizeWorkProfileProvisioning(UserHandle managedProfileUser,
+ Account migratedAccount) {
+ Preconditions.checkCallAuthorization(
+ hasCallingOrSelfPermission(permission.MANAGE_PROFILE_AND_DEVICE_OWNERS));
+
+ if (!isManagedProfile(managedProfileUser.getIdentifier())) {
+ throw new IllegalStateException("Given user is not a managed profile");
+ }
+ ComponentName profileOwnerComponent =
+ mOwners.getProfileOwnerComponent(managedProfileUser.getIdentifier());
+ if (profileOwnerComponent == null) {
+ throw new IllegalStateException("There is no profile owner on the given profile");
+ }
+ Intent primaryProfileSuccessIntent = new Intent(ACTION_MANAGED_PROFILE_PROVISIONED);
+ primaryProfileSuccessIntent.setPackage(profileOwnerComponent.getPackageName());
+ primaryProfileSuccessIntent.addFlags(Intent.FLAG_INCLUDE_STOPPED_PACKAGES
+ | Intent.FLAG_RECEIVER_FOREGROUND);
+ primaryProfileSuccessIntent.putExtra(Intent.EXTRA_USER, managedProfileUser);
+
+ if (migratedAccount != null) {
+ primaryProfileSuccessIntent.putExtra(EXTRA_PROVISIONING_ACCOUNT_TO_MIGRATE,
+ migratedAccount);
+ }
+
+ mContext.sendBroadcastAsUser(primaryProfileSuccessIntent,
+ UserHandle.of(getProfileParentId(managedProfileUser.getIdentifier())));
+ }
+
/**
* Callback called at the beginning of {@link #createAndProvisionManagedProfile(
* ManagedProfileProvisioningParams, String)} after the relevant prechecks have passed.
@@ -18384,14 +18422,8 @@
} else {
preferenceBuilder.setPreference(PROFILE_NETWORK_PREFERENCE_DEFAULT);
}
- List<Integer> allowedUids = Arrays.stream(
- preferentialNetworkServiceConfig.getIncludedUids()).boxed().collect(
- Collectors.toList());
- List<Integer> excludedUids = Arrays.stream(
- preferentialNetworkServiceConfig.getExcludedUids()).boxed().collect(
- Collectors.toList());
- preferenceBuilder.setIncludedUids(allowedUids);
- preferenceBuilder.setExcludedUids(excludedUids);
+ preferenceBuilder.setIncludedUids(preferentialNetworkServiceConfig.getIncludedUids());
+ preferenceBuilder.setExcludedUids(preferentialNetworkServiceConfig.getExcludedUids());
preferenceBuilder.setPreferenceEnterpriseId(
preferentialNetworkServiceConfig.getNetworkId());
@@ -18688,13 +18720,14 @@
mInjector.binderWithCleanCallingIdentity(() -> {
if (mDeviceManagementResourcesProvider.updateDrawables(drawables)) {
sendDrawableUpdatedBroadcast(
- drawables.stream().map(s -> s.getDrawableId()).toArray(String[]::new));
+ drawables.stream().map(s -> s.getDrawableId()).collect(
+ Collectors.toList()));
}
});
}
@Override
- public void resetDrawables(@NonNull String[] drawableIds) {
+ public void resetDrawables(@NonNull List<String> drawableIds) {
Preconditions.checkCallAuthorization(hasCallingOrSelfPermission(
android.Manifest.permission.UPDATE_DEVICE_MANAGEMENT_RESOURCES));
@@ -18715,7 +18748,7 @@
drawableId, drawableStyle, drawableSource));
}
- private void sendDrawableUpdatedBroadcast(String[] drawableIds) {
+ private void sendDrawableUpdatedBroadcast(List<String> drawableIds) {
sendResourceUpdatedBroadcast(EXTRA_RESOURCE_TYPE_DRAWABLE, drawableIds);
}
@@ -18729,12 +18762,12 @@
mInjector.binderWithCleanCallingIdentity(() -> {
if (mDeviceManagementResourcesProvider.updateStrings(strings))
sendStringsUpdatedBroadcast(
- strings.stream().map(s -> s.getStringId()).toArray(String[]::new));
+ strings.stream().map(s -> s.getStringId()).collect(Collectors.toList()));
});
}
@Override
- public void resetStrings(String[] stringIds) {
+ public void resetStrings(@NonNull List<String> stringIds) {
Preconditions.checkCallAuthorization(hasCallingOrSelfPermission(
android.Manifest.permission.UPDATE_DEVICE_MANAGEMENT_RESOURCES));
@@ -18751,13 +18784,13 @@
mDeviceManagementResourcesProvider.getString(stringId));
}
- private void sendStringsUpdatedBroadcast(String[] stringIds) {
+ private void sendStringsUpdatedBroadcast(List<String> stringIds) {
sendResourceUpdatedBroadcast(EXTRA_RESOURCE_TYPE_STRING, stringIds);
}
- private void sendResourceUpdatedBroadcast(int resourceType, String[] resourceIds) {
+ private void sendResourceUpdatedBroadcast(int resourceType, List<String> resourceIds) {
final Intent intent = new Intent(ACTION_DEVICE_POLICY_RESOURCE_UPDATED);
- intent.putExtra(EXTRA_RESOURCE_IDS, resourceIds);
+ intent.putExtra(EXTRA_RESOURCE_IDS, resourceIds.toArray(String[]::new));
intent.putExtra(EXTRA_RESOURCE_TYPE, resourceType);
intent.setFlags(Intent.FLAG_RECEIVER_FOREGROUND);
intent.setFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
@@ -18790,4 +18823,18 @@
mInjector.binderWithCleanCallingIdentity(() -> Settings.Secure.putInt(
mContext.getContentResolver(), MANAGED_PROVISIONING_DPC_DOWNLOADED, setTo));
}
+
+ @Override
+ public boolean shouldAllowBypassingDevicePolicyManagementRoleQualification() {
+ Preconditions.checkCallAuthorization(hasCallingOrSelfPermission(
+ android.Manifest.permission.MANAGE_ROLE_HOLDERS));
+ return mInjector.binderWithCleanCallingIdentity(() -> {
+ if (mUserManager.getUserCount() > 1) {
+ return false;
+ }
+ AccountManager am = AccountManager.get(mContext);
+ Account[] accounts = am.getAccounts();
+ return accounts.length == 0;
+ });
+ }
}
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerServiceShellCommand.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerServiceShellCommand.java
index e1d720c..1fa2f53 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerServiceShellCommand.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerServiceShellCommand.java
@@ -340,7 +340,7 @@
private int runMarkProfileOwnerOnOrganizationOwnedDevice(PrintWriter pw) {
parseArgs(/* canHaveName= */ false);
- mService.markProfileOwnerOnOrganizationOwnedDevice(mComponent, mUserId);
+ mService.setProfileOwnerOnOrganizationOwnedDevice(mComponent, mUserId, true);
pw.printf("Success\n");
return 0;
}
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/Owners.java b/services/devicepolicy/java/com/android/server/devicepolicy/Owners.java
index fe8f223..b0fdd72 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/Owners.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/Owners.java
@@ -620,18 +620,15 @@
}
}
- /**
- * Sets the indicator that the profile owner manages an organization-owned device,
- * then write to file.
- */
- void markProfileOwnerOfOrganizationOwnedDevice(int userId) {
+ /** Set whether the profile owner manages an organization-owned device, then write to file. */
+ void setProfileOwnerOfOrganizationOwnedDevice(int userId, boolean isOrganizationOwnedDevice) {
synchronized (mLock) {
OwnerInfo profileOwner = mProfileOwners.get(userId);
if (profileOwner != null) {
- profileOwner.isOrganizationOwnedDevice = true;
+ profileOwner.isOrganizationOwnedDevice = isOrganizationOwnedDevice;
} else {
Slog.e(TAG, String.format(
- "No profile owner for user %d to set as org-owned.", userId));
+ "No profile owner for user %d to set org-owned flag.", userId));
}
writeProfileOwner(userId);
}
diff --git a/services/tests/PackageManagerServiceTests/unit/src/com/android/server/pm/test/parsing/parcelling/AndroidPackageTest.kt b/services/tests/PackageManagerServiceTests/unit/src/com/android/server/pm/test/parsing/parcelling/AndroidPackageTest.kt
index 8f81e93..7a9c412 100644
--- a/services/tests/PackageManagerServiceTests/unit/src/com/android/server/pm/test/parsing/parcelling/AndroidPackageTest.kt
+++ b/services/tests/PackageManagerServiceTests/unit/src/com/android/server/pm/test/parsing/parcelling/AndroidPackageTest.kt
@@ -143,6 +143,7 @@
AndroidPackage::getLogo,
AndroidPackage::getLocaleConfigRes,
AndroidPackage::getManageSpaceActivityName,
+ AndroidPackage::getMaxSdkVersion,
AndroidPackage::getMemtagMode,
AndroidPackage::getMinSdkVersion,
AndroidPackage::getNativeHeapZeroInitialized,
diff --git a/services/tests/mockingservicestests/AndroidManifest.xml b/services/tests/mockingservicestests/AndroidManifest.xml
index 3cab5ec..7714cf0 100644
--- a/services/tests/mockingservicestests/AndroidManifest.xml
+++ b/services/tests/mockingservicestests/AndroidManifest.xml
@@ -31,6 +31,7 @@
<uses-permission android:name="android.permission.WAKE_LOCK"/>
<uses-permission
android:name="android.permission.OVERRIDE_COMPAT_CHANGE_CONFIG_ON_RELEASE_BUILD"/>
+ <uses-permission android:name="android.permission.STATUS_BAR_SERVICE" />
<!-- needed by MasterClearReceiverTest to display a system dialog -->
<uses-permission android:name="android.permission.INTERNAL_SYSTEM_WINDOW"/>
diff --git a/services/tests/mockingservicestests/src/com/android/server/alarm/AlarmManagerServiceTest.java b/services/tests/mockingservicestests/src/com/android/server/alarm/AlarmManagerServiceTest.java
index f05658b..e096687 100644
--- a/services/tests/mockingservicestests/src/com/android/server/alarm/AlarmManagerServiceTest.java
+++ b/services/tests/mockingservicestests/src/com/android/server/alarm/AlarmManagerServiceTest.java
@@ -494,9 +494,9 @@
final ArgumentCaptor<AlarmManagerService.UninstallReceiver> packageReceiverCaptor =
ArgumentCaptor.forClass(AlarmManagerService.UninstallReceiver.class);
- verify(mMockContext).registerReceiver(packageReceiverCaptor.capture(),
+ verify(mMockContext).registerReceiverForAllUsers(packageReceiverCaptor.capture(),
argThat((filter) -> filter.hasAction(Intent.ACTION_PACKAGE_ADDED)
- && filter.hasAction(Intent.ACTION_PACKAGE_REMOVED)));
+ && filter.hasAction(Intent.ACTION_PACKAGE_REMOVED)), isNull(), isNull());
mPackageChangesReceiver = packageReceiverCaptor.getValue();
assertEquals(mService.mExactAlarmCandidates, Collections.emptySet());
diff --git a/services/tests/mockingservicestests/src/com/android/server/am/BackgroundRestrictionTest.java b/services/tests/mockingservicestests/src/com/android/server/am/BackgroundRestrictionTest.java
index 0535513..d44fb3b 100644
--- a/services/tests/mockingservicestests/src/com/android/server/am/BackgroundRestrictionTest.java
+++ b/services/tests/mockingservicestests/src/com/android/server/am/BackgroundRestrictionTest.java
@@ -51,6 +51,7 @@
import static com.android.internal.notification.SystemNotificationChannels.ABUSIVE_BACKGROUND_APPS;
import static com.android.server.am.AppBatteryTracker.AppBatteryPolicy.getFloatArray;
import static com.android.server.am.AppBatteryTracker.BatteryUsage.BATTERY_USAGE_INDEX_BACKGROUND;
+import static com.android.server.am.AppBatteryTracker.BatteryUsage.BATTERY_USAGE_INDEX_CACHED;
import static com.android.server.am.AppBatteryTracker.BatteryUsage.BATTERY_USAGE_INDEX_FOREGROUND;
import static com.android.server.am.AppBatteryTracker.BatteryUsage.BATTERY_USAGE_INDEX_FOREGROUND_SERVICE;
import static com.android.server.am.AppBatteryTracker.BatteryUsage.BATT_DIMENS;
@@ -58,6 +59,7 @@
import static com.android.server.am.AppRestrictionController.STOCK_PM_FLAGS;
import static com.android.server.am.BaseAppStateTracker.STATE_TYPE_FGS_LOCATION;
import static com.android.server.am.BaseAppStateTracker.STATE_TYPE_FGS_MEDIA_PLAYBACK;
+import static com.android.server.am.BaseAppStateTracker.STATE_TYPE_FGS_WITH_NOTIFICATION;
import static com.android.server.am.BaseAppStateTracker.STATE_TYPE_MEDIA_SESSION;
import static com.android.server.am.BaseAppStateTracker.STATE_TYPE_PERMISSION;
@@ -112,6 +114,7 @@
import android.os.UserHandle;
import android.permission.PermissionManager;
import android.provider.DeviceConfig;
+import android.service.notification.StatusBarNotification;
import android.telephony.TelephonyManager;
import android.util.Log;
import android.util.Pair;
@@ -119,6 +122,7 @@
import androidx.test.runner.AndroidJUnit4;
import com.android.internal.R;
+import com.android.internal.app.IAppOpsService;
import com.android.server.AppStateTracker;
import com.android.server.DeviceIdleInternal;
import com.android.server.am.AppBatteryExemptionTracker.AppBatteryExemptionPolicy;
@@ -231,6 +235,7 @@
@Mock private MediaSessionManager mMediaSessionManager;
@Mock private RoleManager mRoleManager;
@Mock private TelephonyManager mTelephonyManager;
+ @Mock private IAppOpsService mIAppOpsService;
private long mCurrentTimeMillis;
@@ -563,6 +568,7 @@
DeviceConfigSession<Float> bgCurrentDrainBgRestrictedThreshold = null;
DeviceConfigSession<Boolean> bgPromptFgsWithNotiToBgRestricted = null;
DeviceConfigSession<Long> bgNotificationMinInterval = null;
+ DeviceConfigSession<Integer> bgBatteryExemptionTypes = null;
mBgRestrictionController.addAppBackgroundRestrictionListener(listener);
@@ -624,20 +630,29 @@
ConstantsObserver.DEFAULT_BG_ABUSIVE_NOTIFICATION_MINIMAL_INTERVAL_MS);
bgNotificationMinInterval.set(windowMs);
+ bgBatteryExemptionTypes = new DeviceConfigSession<>(
+ DeviceConfig.NAMESPACE_ACTIVITY_MANAGER,
+ AppBatteryPolicy.KEY_BG_CURRENT_DRAIN_EXEMPTED_TYPES,
+ DeviceConfig::getInt,
+ mContext.getResources().getInteger(
+ R.integer.config_bg_current_drain_exempted_types));
+ bgBatteryExemptionTypes.set(0);
+
mCurrentTimeMillis = 10_000L;
doReturn(mCurrentTimeMillis - windowMs).when(stats).getStatsStartTimestamp();
doReturn(mCurrentTimeMillis).when(stats).getStatsEndTimestamp();
doReturn(statsList).when(mBatteryStatsInternal).getBatteryUsageStats(anyObject());
- doReturn(true).when(mNotificationManagerInternal).isNotificationShown(
- testPkgName, null, notificationId, testUser);
mAppFGSTracker.onForegroundServiceStateChanged(testPkgName, testUid,
testPid, true);
mAppFGSTracker.onForegroundServiceNotificationUpdated(
testPkgName, testUid, notificationId);
+ mAppFGSTracker.mNotificationListener.onNotificationPosted(new StatusBarNotification(
+ testPkgName, null, notificationId, null, testUid, testPid,
+ new Notification(), UserHandle.of(testUser), null, mCurrentTimeMillis), null);
runTestBgCurrentDrainMonitorOnce(listener, stats, uids,
new double[]{restrictBucketThresholdMah - 1, 0},
- new double[]{0, restrictBucketThresholdMah - 1}, zeros,
+ new double[]{0, restrictBucketThresholdMah - 1}, zeros, zeros,
() -> {
doReturn(mCurrentTimeMillis).when(stats).getStatsStartTimestamp();
doReturn(mCurrentTimeMillis + windowMs)
@@ -654,7 +669,7 @@
runTestBgCurrentDrainMonitorOnce(listener, stats, uids,
new double[]{restrictBucketThresholdMah + 1, 0},
- new double[]{0, restrictBucketThresholdMah - 1}, zeros,
+ new double[]{0, restrictBucketThresholdMah - 1}, zeros, zeros,
() -> {
doReturn(mCurrentTimeMillis).when(stats).getStatsStartTimestamp();
doReturn(mCurrentTimeMillis + windowMs)
@@ -672,7 +687,7 @@
runTestBgCurrentDrainMonitorOnce(listener, stats, uids,
new double[]{restrictBucketThresholdMah - 1, 0},
- new double[]{0, restrictBucketThresholdMah - 1}, zeros,
+ new double[]{0, restrictBucketThresholdMah - 1}, zeros, zeros,
() -> {
doReturn(mCurrentTimeMillis).when(stats).getStatsStartTimestamp();
doReturn(mCurrentTimeMillis + windowMs)
@@ -696,7 +711,7 @@
// Trigger user interaction.
runTestBgCurrentDrainMonitorOnce(listener, stats, uids,
new double[]{restrictBucketThresholdMah - 1, 0},
- new double[]{0, restrictBucketThresholdMah - 1}, zeros,
+ new double[]{0, restrictBucketThresholdMah - 1}, zeros, zeros,
() -> {
doReturn(mCurrentTimeMillis).when(stats).getStatsStartTimestamp();
doReturn(mCurrentTimeMillis + windowMs)
@@ -719,8 +734,8 @@
clearInvocations(mInjector.getAppStandbyInternal());
runTestBgCurrentDrainMonitorOnce(listener, stats, uids,
- new double[]{restrictBucketThresholdMah + 1, 0},
- new double[]{0, restrictBucketThresholdMah - 1}, zeros,
+ zeros, new double[]{0, restrictBucketThresholdMah - 1},
+ zeros, new double[]{restrictBucketThresholdMah + 1, 0},
() -> {
doReturn(mCurrentTimeMillis).when(stats).getStatsStartTimestamp();
doReturn(mCurrentTimeMillis + windowMs)
@@ -738,8 +753,8 @@
clearInvocations(mInjector.getAppStandbyInternal());
// Drain a bit more, there shouldn't be any level changes.
runTestBgCurrentDrainMonitorOnce(listener, stats, uids,
- new double[]{restrictBucketThresholdMah + 2, 0},
- new double[]{0, restrictBucketThresholdMah - 1}, zeros,
+ zeros, new double[]{0, restrictBucketThresholdMah - 1},
+ zeros, new double[]{restrictBucketThresholdMah + 2, 0},
() -> {
doReturn(mCurrentTimeMillis).when(stats).getStatsStartTimestamp();
doReturn(mCurrentTimeMillis + windowMs)
@@ -771,7 +786,7 @@
runTestBgCurrentDrainMonitorOnce(listener, stats, uids,
new double[]{bgRestrictedThresholdMah + 1, 0},
- new double[]{0, restrictBucketThresholdMah - 1}, zeros,
+ new double[]{0, restrictBucketThresholdMah - 1}, zeros, zeros,
() -> {
doReturn(mCurrentTimeMillis).when(stats).getStatsStartTimestamp();
doReturn(mCurrentTimeMillis + windowMs)
@@ -809,7 +824,7 @@
runTestBgCurrentDrainMonitorOnce(listener, stats, uids,
new double[]{bgRestrictedThresholdMah + 1, 0},
- new double[]{0, restrictBucketThresholdMah - 1}, zeros,
+ new double[]{0, restrictBucketThresholdMah - 1}, zeros, zeros,
() -> {
doReturn(mCurrentTimeMillis).when(stats).getStatsStartTimestamp();
doReturn(mCurrentTimeMillis + windowMs)
@@ -848,7 +863,7 @@
runTestBgCurrentDrainMonitorOnce(listener, stats, uids,
new double[]{bgRestrictedThresholdMah + 1, 0},
- new double[]{0, restrictBucketThresholdMah - 1}, zeros,
+ new double[]{0, restrictBucketThresholdMah - 1}, zeros, zeros,
() -> {
doReturn(mCurrentTimeMillis).when(stats).getStatsStartTimestamp();
doReturn(mCurrentTimeMillis + windowMs)
@@ -912,6 +927,7 @@
closeIfNotNull(bgCurrentDrainBgRestrictedThreshold);
closeIfNotNull(bgPromptFgsWithNotiToBgRestricted);
closeIfNotNull(bgNotificationMinInterval);
+ closeIfNotNull(bgBatteryExemptionTypes);
}
}
@@ -1247,14 +1263,15 @@
List<Pair<List<MediaController>, Long>> mediaControllers, List<Long> topStateChanges,
VerificationMode mode) throws Exception {
runExemptionTestOnce(
- packageName, uid, pid, serviceType, sleepMs, true, perm, mediaControllers,
+ packageName, uid, pid, serviceType, sleepMs, true, false, perm, mediaControllers,
topStateChanges, true, true,
() -> checkNotificationShown(new String[] {packageName}, mode, false)
);
}
private void runExemptionTestOnce(String packageName, int uid, int pid,
- int serviceType, long sleepMs, boolean stopAfterSleep, String perm,
+ int serviceType, long sleepMs, boolean stopAfterSleep,
+ boolean withNotification, String perm,
List<Pair<List<MediaController>, Long>> mediaControllers,
List<Long> topStateChanges, boolean resetFGSTracker, boolean resetController,
RunnableWithException r) throws Exception {
@@ -1299,7 +1316,20 @@
FOREGROUND_SERVICE_TYPE_NONE);
}
}
-
+ if (withNotification) {
+ final int notificationId = 1000;
+ mAppFGSTracker.onForegroundServiceNotificationUpdated(
+ packageName, uid, notificationId);
+ final StatusBarNotification noti = new StatusBarNotification(
+ packageName, null, notificationId, null, uid, pid,
+ new Notification(), UserHandle.of(UserHandle.getUserId(uid)),
+ null, mCurrentTimeMillis);
+ mAppFGSTracker.mNotificationListener.onNotificationPosted(noti, null);
+ Thread.sleep(sleepMs);
+ if (stopAfterSleep) {
+ mAppFGSTracker.mNotificationListener.onNotificationRemoved(noti, null, 0);
+ }
+ }
if (perm != null) {
doReturn(PERMISSION_GRANTED)
.when(mPermissionManagerServiceInternal)
@@ -1510,7 +1540,8 @@
mContext.getResources().getInteger(
R.integer.config_bg_current_drain_exempted_types));
bgBatteryExemptionTypes.set(STATE_TYPE_MEDIA_SESSION | STATE_TYPE_FGS_MEDIA_PLAYBACK
- | STATE_TYPE_FGS_LOCATION | STATE_TYPE_PERMISSION);
+ | STATE_TYPE_FGS_LOCATION | STATE_TYPE_PERMISSION
+ | STATE_TYPE_FGS_WITH_NOTIFICATION);
bgPermissionMonitorEnabled = new DeviceConfigSession<>(
DeviceConfig.NAMESPACE_ACTIVITY_MANAGER,
@@ -1543,19 +1574,19 @@
// Run with a media playback service which starts/stops immediately, we should
// goto the restricted bucket.
runTestBgCurrentDrainExemptionOnce(testPkgName1, testUid1, testPid1,
- FOREGROUND_SERVICE_TYPE_MEDIA_PLAYBACK, 0, true,
+ FOREGROUND_SERVICE_TYPE_MEDIA_PLAYBACK, 0, true, false,
null, null, null, listener, stats, uids,
new double[]{restrictBucketThresholdMah + 1, 0},
- new double[]{0, restrictBucketThresholdMah - 1}, zeros,
+ new double[]{0, restrictBucketThresholdMah - 1}, zeros, zeros,
false, RESTRICTION_LEVEL_RESTRICTED_BUCKET, timeout, true,
- null, windowMs, null, null, null);
+ null, windowMs, null, null, null, null);
// Run with a media playback service with extended time. We should be back to normal.
runTestBgCurrentDrainExemptionOnce(testPkgName1, testUid1, testPid1,
FOREGROUND_SERVICE_TYPE_MEDIA_PLAYBACK, bgMediaPlaybackMinDuration * 2, false,
- null, null, null, listener, stats, uids,
+ false, null, null, null, listener, stats, uids,
new double[]{restrictBucketThresholdMah + 1, 0},
- new double[]{0, restrictBucketThresholdMah - 1}, zeros,
+ new double[]{0, restrictBucketThresholdMah - 1}, zeros, zeros,
true, RESTRICTION_LEVEL_ADAPTIVE_BUCKET, timeout, false,
() -> {
// A user interaction will bring it back to normal.
@@ -1572,116 +1603,116 @@
eq(REASON_SUB_FORCED_SYSTEM_FLAG_ABUSE),
eq(REASON_MAIN_USAGE),
eq(REASON_SUB_USAGE_USER_INTERACTION));
- }, windowMs, null, null, null);
+ }, windowMs, null, null, null, null);
// Start over.
resetBgRestrictionController();
- setUidBatteryConsumptions(stats, uids, zeros, zeros, zeros);
+ setUidBatteryConsumptions(stats, uids, zeros, zeros, zeros, zeros);
mAppBatteryPolicy.reset();
// Run with a media playback service with extended time, with higher current drain.
runTestBgCurrentDrainExemptionOnce(testPkgName1, testUid1, testPid1,
FOREGROUND_SERVICE_TYPE_MEDIA_PLAYBACK, bgMediaPlaybackMinDuration * 2, false,
- null, null, null, listener, stats, uids,
+ false, null, null, null, listener, stats, uids,
new double[]{restrictBucketHighThresholdMah - 1, 0},
- new double[]{0, restrictBucketThresholdMah - 1}, zeros,
+ new double[]{0, restrictBucketThresholdMah - 1}, zeros, zeros,
true, RESTRICTION_LEVEL_RESTRICTED_BUCKET, timeout, true,
- null, windowMs, null, null, null);
+ null, windowMs, null, null, null, null);
// Run with a media playback service with extended time, with even higher current drain.
runTestBgCurrentDrainExemptionOnce(testPkgName1, testUid1, testPid1,
FOREGROUND_SERVICE_TYPE_MEDIA_PLAYBACK, bgMediaPlaybackMinDuration * 2, false,
- null, null, null, listener, stats, uids,
+ false, null, null, null, listener, stats, uids,
new double[]{restrictBucketHighThresholdMah + 1, 0},
- new double[]{0, restrictBucketThresholdMah - 1}, zeros,
+ new double[]{0, restrictBucketThresholdMah - 1}, zeros, zeros,
false, RESTRICTION_LEVEL_RESTRICTED_BUCKET, timeout, false,
- null, windowMs, null, null, null);
+ null, windowMs, null, null, null, null);
// Start over.
resetBgRestrictionController();
- setUidBatteryConsumptions(stats, uids, zeros, zeros, zeros);
+ setUidBatteryConsumptions(stats, uids, zeros, zeros, zeros, zeros);
mAppBatteryPolicy.reset();
// Run with a media session with extended time, with higher current drain.
runTestBgCurrentDrainExemptionOnce(testPkgName1, testUid1, testPid1,
- FOREGROUND_SERVICE_TYPE_NONE, bgMediaPlaybackMinDuration * 2, false, null,
- List.of(Pair.create(createMediaControllers(new String[] {testPkgName1},
+ FOREGROUND_SERVICE_TYPE_NONE, bgMediaPlaybackMinDuration * 2, false, false,
+ null, List.of(Pair.create(createMediaControllers(new String[] {testPkgName1},
new int[] {testUid1}), bgMediaPlaybackMinDuration * 2)),
null, listener, stats, uids,
new double[]{restrictBucketHighThresholdMah - 1, 0},
- new double[]{0, restrictBucketThresholdMah - 1}, zeros,
+ new double[]{0, restrictBucketThresholdMah - 1}, zeros, zeros,
true, RESTRICTION_LEVEL_RESTRICTED_BUCKET, timeout, true,
- null, windowMs, null, null, null);
+ null, windowMs, null, null, null, null);
// Run with a media session with extended time, with even higher current drain.
runTestBgCurrentDrainExemptionOnce(testPkgName1, testUid1, testPid1,
- FOREGROUND_SERVICE_TYPE_NONE, bgMediaPlaybackMinDuration * 2, false, null,
- List.of(Pair.create(createMediaControllers(new String[] {testPkgName1},
+ FOREGROUND_SERVICE_TYPE_NONE, bgMediaPlaybackMinDuration * 2, false, false,
+ null, List.of(Pair.create(createMediaControllers(new String[] {testPkgName1},
new int[] {testUid1}), bgMediaPlaybackMinDuration * 2)),
null, listener, stats, uids,
new double[]{restrictBucketHighThresholdMah + 1, 0},
- new double[]{0, restrictBucketThresholdMah - 1}, zeros,
+ new double[]{0, restrictBucketThresholdMah - 1}, zeros, zeros,
false, RESTRICTION_LEVEL_RESTRICTED_BUCKET, timeout, false,
- null, windowMs, null, null, null);
+ null, windowMs, null, null, null, null);
// Start over.
resetBgRestrictionController();
- setUidBatteryConsumptions(stats, uids, zeros, zeros, zeros);
+ setUidBatteryConsumptions(stats, uids, zeros, zeros, zeros, zeros);
mAppBatteryPolicy.reset();
// Run with a media session with extended time, with moderate current drain,
// but it ran on the top when the location service is active.
runTestBgCurrentDrainExemptionOnce(testPkgName1, testUid1, testPid1,
- FOREGROUND_SERVICE_TYPE_NONE, bgMediaPlaybackMinDuration * 2, false, null,
- List.of(Pair.create(createMediaControllers(new String[] {testPkgName1},
+ FOREGROUND_SERVICE_TYPE_NONE, bgMediaPlaybackMinDuration * 2, false, false,
+ null, List.of(Pair.create(createMediaControllers(new String[] {testPkgName1},
new int[] {testUid1}), bgMediaPlaybackMinDuration * 2)),
List.of(0L, timeout * 2), listener, stats, uids,
new double[]{restrictBucketThresholdMah + 1, 0},
- new double[]{0, restrictBucketThresholdMah - 1}, zeros,
+ new double[]{0, restrictBucketThresholdMah - 1}, zeros, zeros,
false, RESTRICTION_LEVEL_RESTRICTED_BUCKET, timeout, true,
- null, windowMs, null, null, null);
+ null, windowMs, null, null, null, null);
// Start over.
resetBgRestrictionController();
- setUidBatteryConsumptions(stats, uids, zeros, zeros, zeros);
+ setUidBatteryConsumptions(stats, uids, zeros, zeros, zeros, zeros);
mAppBatteryPolicy.reset();
// Run with a location service with extended time, with higher current drain.
runTestBgCurrentDrainExemptionOnce(testPkgName1, testUid1, testPid1,
- FOREGROUND_SERVICE_TYPE_LOCATION, bgMediaPlaybackMinDuration * 2, false,
+ FOREGROUND_SERVICE_TYPE_LOCATION, bgMediaPlaybackMinDuration * 2, false, false,
null, null, null, listener, stats, uids,
new double[]{restrictBucketHighThresholdMah - 1, 0},
- new double[]{0, restrictBucketThresholdMah - 1}, zeros,
+ new double[]{0, restrictBucketThresholdMah - 1}, zeros, zeros,
true, RESTRICTION_LEVEL_RESTRICTED_BUCKET, timeout, true,
- null, windowMs, null, null, null);
+ null, windowMs, null, null, null, null);
// Run with a location service with extended time, with even higher current drain.
runTestBgCurrentDrainExemptionOnce(testPkgName1, testUid1, testPid1,
- FOREGROUND_SERVICE_TYPE_LOCATION, bgMediaPlaybackMinDuration * 2, false,
+ FOREGROUND_SERVICE_TYPE_LOCATION, bgMediaPlaybackMinDuration * 2, false, false,
null, null, null, listener, stats, uids,
new double[]{restrictBucketHighThresholdMah + 1, 0},
- new double[]{0, restrictBucketThresholdMah - 1}, zeros,
+ new double[]{0, restrictBucketThresholdMah - 1}, zeros, zeros,
false, RESTRICTION_LEVEL_RESTRICTED_BUCKET, timeout, false,
- null, windowMs, null, null, null);
+ null, windowMs, null, null, null, null);
// Start over.
resetBgRestrictionController();
- setUidBatteryConsumptions(stats, uids, zeros, zeros, zeros);
+ setUidBatteryConsumptions(stats, uids, zeros, zeros, zeros, zeros);
mAppBatteryPolicy.reset();
// Run with a location service with extended time, with moderate current drain,
// but it ran on the top when the location service is active.
runTestBgCurrentDrainExemptionOnce(testPkgName1, testUid1, testPid1,
- FOREGROUND_SERVICE_TYPE_LOCATION, bgMediaPlaybackMinDuration * 2, false,
+ FOREGROUND_SERVICE_TYPE_LOCATION, bgMediaPlaybackMinDuration * 2, false, false,
null, null, List.of(0L, timeout * 2), listener, stats, uids,
new double[]{restrictBucketThresholdMah + 1, 0},
- new double[]{0, restrictBucketThresholdMah - 1}, zeros,
+ new double[]{0, restrictBucketThresholdMah - 1}, zeros, zeros,
false, RESTRICTION_LEVEL_RESTRICTED_BUCKET, timeout, true,
- null, windowMs, null, null, null);
+ null, windowMs, null, null, null, null);
// Start over.
resetBgRestrictionController();
- setUidBatteryConsumptions(stats, uids, zeros, zeros, zeros);
+ setUidBatteryConsumptions(stats, uids, zeros, zeros, zeros, zeros);
mAppBatteryPolicy.reset();
// Turn off the higher threshold for bg location access.
@@ -1689,25 +1720,25 @@
// Run with bg location permission, with moderate current drain.
runTestBgCurrentDrainExemptionOnce(testPkgName1, testUid1, testPid1,
- FOREGROUND_SERVICE_TYPE_NONE, 0, false,
+ FOREGROUND_SERVICE_TYPE_NONE, 0, false, false,
ACCESS_BACKGROUND_LOCATION, null, null, listener, stats, uids,
new double[]{restrictBucketThresholdMah - 1, 0},
- new double[]{0, restrictBucketThresholdMah - 1}, zeros,
+ new double[]{0, restrictBucketThresholdMah - 1}, zeros, zeros,
true, RESTRICTION_LEVEL_RESTRICTED_BUCKET, timeout, true,
- null, windowMs, null, null, null);
+ null, windowMs, null, null, null, null);
// Run with bg location permission, with a bit higher current drain.
runTestBgCurrentDrainExemptionOnce(testPkgName1, testUid1, testPid1,
- FOREGROUND_SERVICE_TYPE_NONE, 0, false,
+ FOREGROUND_SERVICE_TYPE_NONE, 0, false, false,
ACCESS_BACKGROUND_LOCATION, null, null, listener, stats, uids,
new double[]{restrictBucketThresholdMah + 1, 0},
- new double[]{0, restrictBucketThresholdMah - 1}, zeros,
+ new double[]{0, restrictBucketThresholdMah - 1}, zeros, zeros,
false, RESTRICTION_LEVEL_RESTRICTED_BUCKET, timeout, true,
- null, windowMs, null, null, null);
+ null, windowMs, null, null, null, null);
// Start over.
resetBgRestrictionController();
- setUidBatteryConsumptions(stats, uids, zeros, zeros, zeros);
+ setUidBatteryConsumptions(stats, uids, zeros, zeros, zeros, zeros);
mAppBatteryPolicy.reset();
// Turn on the higher threshold for bg location access.
@@ -1715,21 +1746,21 @@
// Run with bg location permission, with higher current drain.
runTestBgCurrentDrainExemptionOnce(testPkgName1, testUid1, testPid1,
- FOREGROUND_SERVICE_TYPE_NONE, 0, false,
+ FOREGROUND_SERVICE_TYPE_NONE, 0, false, false,
ACCESS_BACKGROUND_LOCATION , null, null, listener, stats, uids,
new double[]{restrictBucketHighThresholdMah - 1, 0},
- new double[]{0, restrictBucketThresholdMah - 1}, zeros,
+ new double[]{0, restrictBucketThresholdMah - 1}, zeros, zeros,
true , RESTRICTION_LEVEL_RESTRICTED_BUCKET, timeout, false,
- null, windowMs, null, null, null);
+ null, windowMs, null, null, null, null);
// Run with bg location permission, with even higher current drain.
runTestBgCurrentDrainExemptionOnce(testPkgName1, testUid1, testPid1,
- FOREGROUND_SERVICE_TYPE_NONE, 0, false,
+ FOREGROUND_SERVICE_TYPE_NONE, 0, false, false,
ACCESS_BACKGROUND_LOCATION , null, null, listener, stats, uids,
new double[]{restrictBucketHighThresholdMah + 1, 0},
- new double[]{0, restrictBucketThresholdMah - 1}, zeros,
+ new double[]{0, restrictBucketThresholdMah - 1}, zeros, zeros,
false, RESTRICTION_LEVEL_RESTRICTED_BUCKET, timeout, false,
- null, windowMs, null, null, null);
+ null, windowMs, null, null, null, null);
// Now turn off the event duration based feature flag.
bgCurrentDrainEventDurationBasedThresholdEnabled.set(false);
@@ -1738,7 +1769,7 @@
// Start over.
resetBgRestrictionController();
- setUidBatteryConsumptions(stats, uids, zeros, zeros, zeros);
+ setUidBatteryConsumptions(stats, uids, zeros, zeros, zeros, zeros);
mAppBatteryPolicy.reset();
waitForIdleHandler(mBgRestrictionController.getBackgroundHandler());
@@ -1746,19 +1777,19 @@
// Run with a media playback service which starts/stops immediately, we should
// goto the restricted bucket.
runTestBgCurrentDrainExemptionOnce(testPkgName1, testUid1, testPid1,
- FOREGROUND_SERVICE_TYPE_MEDIA_PLAYBACK, 0, true,
+ FOREGROUND_SERVICE_TYPE_MEDIA_PLAYBACK, 0, true, false,
null, null, null, listener, stats, uids,
new double[]{restrictBucketThresholdMah + 1, 0},
- new double[]{0, restrictBucketThresholdMah - 1}, zeros,
+ new double[]{0, restrictBucketThresholdMah - 1}, zeros, zeros,
false, RESTRICTION_LEVEL_RESTRICTED_BUCKET, timeout, true,
- null, windowMs, null, null, null);
+ null, windowMs, null, null, null, null);
// Run with a media playback service with extended time. We should be back to normal.
runTestBgCurrentDrainExemptionOnce(testPkgName1, testUid1, testPid1,
FOREGROUND_SERVICE_TYPE_MEDIA_PLAYBACK, bgMediaPlaybackMinDuration * 2, false,
- null, null, null, listener, stats, uids,
+ false, null, null, null, listener, stats, uids,
new double[]{restrictBucketThresholdMah + 1, 0},
- new double[]{0, restrictBucketThresholdMah - 1}, zeros,
+ new double[]{0, restrictBucketThresholdMah - 1}, zeros, zeros,
true, RESTRICTION_LEVEL_ADAPTIVE_BUCKET, timeout, false,
() -> {
// A user interaction will bring it back to normal.
@@ -1775,121 +1806,164 @@
eq(REASON_SUB_FORCED_SYSTEM_FLAG_ABUSE),
eq(REASON_MAIN_USAGE),
eq(REASON_SUB_USAGE_USER_INTERACTION));
- }, windowMs, null, null, null);
+ }, windowMs, null, null, null, null);
// Start over.
resetBgRestrictionController();
- setUidBatteryConsumptions(stats, uids, zeros, zeros, zeros);
+ setUidBatteryConsumptions(stats, uids, zeros, zeros, zeros, zeros);
mAppBatteryPolicy.reset();
- final double[] initialBg = {1, 1}, initialFgs = {1, 1}, initialFg = zeros;
+ final double[] initialBg = {1, 1}, initialFgs = {1, 1}, initialFg = zeros,
+ initialCached = {1, 1};
// Run with a media playback service with extended time, with higher current drain.
runTestBgCurrentDrainExemptionOnce(testPkgName1, testUid1, testPid1,
FOREGROUND_SERVICE_TYPE_MEDIA_PLAYBACK, bgMediaPlaybackMinDuration * 2, false,
- null, null, null, listener, stats, uids,
+ false, null, null, null, listener, stats, uids,
new double[]{restrictBucketHighThresholdMah - 1, 0},
- new double[]{0, restrictBucketThresholdMah - 1}, zeros,
+ new double[]{0, restrictBucketThresholdMah - 1}, zeros, zeros,
true, RESTRICTION_LEVEL_RESTRICTED_BUCKET, timeout, true,
- null, windowMs, initialBg, initialFgs, initialFg);
+ null, windowMs, initialBg, initialFgs, initialFg, initialCached);
// Run with a media playback service with extended time, with even higher current drain,
// it still should stay in the current restriction level as we exempt the media
// playback.
runTestBgCurrentDrainExemptionOnce(testPkgName1, testUid1, testPid1,
FOREGROUND_SERVICE_TYPE_MEDIA_PLAYBACK, bgMediaPlaybackMinDuration * 2, false,
- null, null, null, listener, stats, uids,
+ false, null, null, null, listener, stats, uids,
new double[]{restrictBucketHighThresholdMah + 100, 0},
- new double[]{0, restrictBucketThresholdMah - 1}, zeros,
+ new double[]{0, restrictBucketThresholdMah - 1}, zeros, zeros,
true, RESTRICTION_LEVEL_RESTRICTED_BUCKET, timeout, false,
- null, windowMs, initialBg, initialFgs, initialFg);
+ null, windowMs, initialBg, initialFgs, initialFg, initialCached);
// Set the policy to exempt media session and permission.
bgBatteryExemptionTypes.set(STATE_TYPE_MEDIA_SESSION | STATE_TYPE_PERMISSION);
// Start over.
resetBgRestrictionController();
- setUidBatteryConsumptions(stats, uids, zeros, zeros, zeros);
+ setUidBatteryConsumptions(stats, uids, zeros, zeros, zeros, zeros);
mAppBatteryPolicy.reset();
// Run with coarse location permission, with high current drain.
runTestBgCurrentDrainExemptionOnce(testPkgName1, testUid1, testPid1,
- FOREGROUND_SERVICE_TYPE_NONE, 0, false,
+ FOREGROUND_SERVICE_TYPE_NONE, 0, false, false,
ACCESS_COARSE_LOCATION, null, null, listener, stats, uids,
new double[]{restrictBucketThresholdMah + 1, 0},
- new double[]{0, restrictBucketThresholdMah - 1}, zeros,
+ new double[]{0, restrictBucketThresholdMah - 1}, zeros, zeros,
false, RESTRICTION_LEVEL_RESTRICTED_BUCKET, timeout, true,
- null, windowMs, initialBg, initialFgs, initialFg);
+ null, windowMs, initialBg, initialFgs, initialFg, initialCached);
// Start over.
resetBgRestrictionController();
- setUidBatteryConsumptions(stats, uids, zeros, zeros, zeros);
+ setUidBatteryConsumptions(stats, uids, zeros, zeros, zeros, zeros);
mAppBatteryPolicy.reset();
// Run with fine location permission, with high current drain.
runTestBgCurrentDrainExemptionOnce(testPkgName1, testUid1, testPid1,
- FOREGROUND_SERVICE_TYPE_NONE, 0, false,
+ FOREGROUND_SERVICE_TYPE_NONE, 0, false, false,
ACCESS_FINE_LOCATION, null, null, listener, stats, uids,
new double[]{restrictBucketThresholdMah + 1, 0},
- new double[]{0, restrictBucketThresholdMah - 1}, zeros,
+ new double[]{0, restrictBucketThresholdMah - 1}, zeros, zeros,
true, RESTRICTION_LEVEL_RESTRICTED_BUCKET, timeout, true,
- null, windowMs, initialBg, initialFgs, initialFg);
+ null, windowMs, initialBg, initialFgs, initialFg, initialCached);
// Start over.
resetBgRestrictionController();
- setUidBatteryConsumptions(stats, uids, zeros, zeros, zeros);
+ setUidBatteryConsumptions(stats, uids, zeros, zeros, zeros, zeros);
mAppBatteryPolicy.reset();
// Run with a media session with extended time, with higher current drain.
runTestBgCurrentDrainExemptionOnce(testPkgName1, testUid1, testPid1,
- FOREGROUND_SERVICE_TYPE_NONE, bgMediaPlaybackMinDuration * 2, false, null,
- List.of(Pair.create(createMediaControllers(new String[] {testPkgName1},
+ FOREGROUND_SERVICE_TYPE_NONE, bgMediaPlaybackMinDuration * 2, false, false,
+ null, List.of(Pair.create(createMediaControllers(new String[] {testPkgName1},
new int[] {testUid1}), bgMediaPlaybackMinDuration * 2)),
null, listener, stats, uids,
new double[]{restrictBucketHighThresholdMah - 1, 0},
- new double[]{0, restrictBucketThresholdMah - 1}, zeros,
+ new double[]{0, restrictBucketThresholdMah - 1}, zeros, zeros,
true, RESTRICTION_LEVEL_RESTRICTED_BUCKET, timeout, true,
- null, windowMs, initialBg, initialFgs, initialFg);
+ null, windowMs, initialBg, initialFgs, initialFg, initialCached);
// Run with a media session with extended time, with even higher current drain.
// it still should stay in the current restriction level as we exempt the media
// session.
runTestBgCurrentDrainExemptionOnce(testPkgName1, testUid1, testPid1,
- FOREGROUND_SERVICE_TYPE_NONE, bgMediaPlaybackMinDuration * 2, false, null,
- List.of(Pair.create(createMediaControllers(new String[] {testPkgName1},
+ FOREGROUND_SERVICE_TYPE_NONE, bgMediaPlaybackMinDuration * 2, false, false,
+ null, List.of(Pair.create(createMediaControllers(new String[] {testPkgName1},
new int[] {testUid1}), bgMediaPlaybackMinDuration * 2)),
null, listener, stats, uids,
new double[]{restrictBucketHighThresholdMah + 100, 0},
- new double[]{0, restrictBucketThresholdMah - 1}, zeros,
+ new double[]{0, restrictBucketThresholdMah - 1}, zeros, zeros,
true, RESTRICTION_LEVEL_RESTRICTED_BUCKET, timeout, true,
- null, windowMs, initialBg, initialFgs, initialFg);
+ null, windowMs, initialBg, initialFgs, initialFg, initialCached);
+
+ // Set the policy to exempt fgs with notifications.
+ bgBatteryExemptionTypes.set(STATE_TYPE_FGS_WITH_NOTIFICATION);
+ // Start over.
+ resetBgRestrictionController();
+ setUidBatteryConsumptions(stats, uids, zeros, zeros, zeros, zeros);
+ mAppBatteryPolicy.reset();
+
+ // Run with a FGS with notification posted/removed immediately, we should
+ // goto the restricted bucket.
+ runTestBgCurrentDrainExemptionOnce(testPkgName1, testUid1, testPid1,
+ FOREGROUND_SERVICE_TYPE_NONE, 0, true, true,
+ null, null, null, listener, stats, uids,
+ new double[]{restrictBucketThresholdMah + 1, 0},
+ new double[]{0, restrictBucketThresholdMah - 1}, zeros, zeros,
+ false, RESTRICTION_LEVEL_RESTRICTED_BUCKET, timeout, true,
+ null, windowMs, null, null, null, null);
+
+ // Run with a service with notification for extended time. We should be back to normal.
+ runTestBgCurrentDrainExemptionOnce(testPkgName1, testUid1, testPid1,
+ FOREGROUND_SERVICE_TYPE_NONE, bgMediaPlaybackMinDuration * 2, false,
+ true, null, null, null, listener, stats, uids,
+ new double[]{restrictBucketThresholdMah + 1, 0},
+ new double[]{0, restrictBucketThresholdMah - 1}, zeros, zeros,
+ true, RESTRICTION_LEVEL_ADAPTIVE_BUCKET, timeout, false,
+ () -> {
+ // A user interaction will bring it back to normal.
+ mIdleStateListener.onUserInteractionStarted(testPkgName1,
+ UserHandle.getUserId(testUid1));
+ waitForIdleHandler(mBgRestrictionController.getBackgroundHandler());
+ // It should have been back to normal.
+ listener.verify(timeout, testUid1, testPkgName1,
+ RESTRICTION_LEVEL_ADAPTIVE_BUCKET);
+ verify(mInjector.getAppStandbyInternal(), times(1)).maybeUnrestrictApp(
+ eq(testPkgName1),
+ eq(UserHandle.getUserId(testUid1)),
+ eq(REASON_MAIN_FORCED_BY_SYSTEM),
+ eq(REASON_SUB_FORCED_SYSTEM_FLAG_ABUSE),
+ eq(REASON_MAIN_USAGE),
+ eq(REASON_SUB_USAGE_USER_INTERACTION));
+ }, windowMs, null, null, null, null);
// Set the policy to exempt all.
bgBatteryExemptionTypes.set(STATE_TYPE_MEDIA_SESSION | STATE_TYPE_FGS_MEDIA_PLAYBACK
- | STATE_TYPE_FGS_LOCATION | STATE_TYPE_PERMISSION);
+ | STATE_TYPE_FGS_LOCATION | STATE_TYPE_PERMISSION
+ | STATE_TYPE_FGS_WITH_NOTIFICATION);
// Start over.
resetBgRestrictionController();
- setUidBatteryConsumptions(stats, uids, zeros, zeros, zeros);
+ setUidBatteryConsumptions(stats, uids, zeros, zeros, zeros, zeros);
mAppBatteryPolicy.reset();
// Run with a location service with extended time, with higher current drain.
runTestBgCurrentDrainExemptionOnce(testPkgName1, testUid1, testPid1,
- FOREGROUND_SERVICE_TYPE_LOCATION, bgMediaPlaybackMinDuration * 2, false,
+ FOREGROUND_SERVICE_TYPE_LOCATION, bgMediaPlaybackMinDuration * 2, false, false,
null, null, null, listener, stats, uids,
new double[]{restrictBucketHighThresholdMah - 1, 0},
- new double[]{0, restrictBucketThresholdMah - 1}, zeros,
+ new double[]{0, restrictBucketThresholdMah - 1}, zeros, zeros,
true, RESTRICTION_LEVEL_RESTRICTED_BUCKET, timeout, true,
- null, windowMs, initialBg, initialFgs, initialFg);
+ null, windowMs, initialBg, initialFgs, initialFg, initialCached);
// Run with a location service with extended time, with even higher current drain.
// it still should stay in the current restriction level as we exempt the location.
runTestBgCurrentDrainExemptionOnce(testPkgName1, testUid1, testPid1,
- FOREGROUND_SERVICE_TYPE_LOCATION, bgMediaPlaybackMinDuration * 2, false,
+ FOREGROUND_SERVICE_TYPE_LOCATION, bgMediaPlaybackMinDuration * 2, false, false,
null, null, null, listener, stats, uids,
new double[]{restrictBucketHighThresholdMah + 100, 0},
- new double[]{0, restrictBucketThresholdMah - 1}, zeros,
+ new double[]{0, restrictBucketThresholdMah - 1}, zeros, zeros,
true, RESTRICTION_LEVEL_RESTRICTED_BUCKET, timeout, false,
- null, windowMs, initialBg, initialFgs, initialFg);
+ null, windowMs, initialBg, initialFgs, initialFg, initialCached);
} finally {
closeIfNotNull(bgCurrentDrainMonitor);
closeIfNotNull(bgCurrentDrainWindow);
@@ -1909,19 +1983,20 @@
}
private void runTestBgCurrentDrainExemptionOnce(String packageName, int uid, int pid,
- int serviceType, long sleepMs, boolean stopAfterSleep, String perm,
- List<Pair<List<MediaController>, Long>> mediaControllers,
+ int serviceType, long sleepMs, boolean stopAfterSleep, boolean withNotification,
+ String perm, List<Pair<List<MediaController>, Long>> mediaControllers,
List<Long> topStateChanges, TestAppRestrictionLevelListener listener,
BatteryUsageStats stats, int[] uids, double[] bg, double[] fgs, double[] fg,
- boolean expectingTimeout, int expectingLevel, long timeout, boolean resetFGSTracker,
- RunnableWithException extraVerifiers, long windowMs,
- double[] initialBg, double[] initialFgs, double[] initialFg) throws Exception {
+ double[] cached, boolean expectingTimeout, int expectingLevel, long timeout,
+ boolean resetFGSTracker, RunnableWithException extraVerifiers, long windowMs,
+ double[] initialBg, double[] initialFgs, double[] initialFg, double[] initialCached)
+ throws Exception {
listener.mLatchHolder[0] = new CountDownLatch(1);
if (initialBg != null) {
doReturn(mCurrentTimeMillis).when(stats).getStatsStartTimestamp();
doReturn(mCurrentTimeMillis + windowMs).when(stats).getStatsEndTimestamp();
mCurrentTimeMillis += windowMs + 1;
- setUidBatteryConsumptions(stats, uids, initialBg, initialFgs, initialFg);
+ setUidBatteryConsumptions(stats, uids, initialBg, initialFgs, initialFg, initialCached);
mAppBatteryExemptionTracker.reset();
mAppBatteryPolicy.reset();
}
@@ -1936,13 +2011,13 @@
}
waitForIdleHandler(mBgRestrictionController.getBackgroundHandler());
runExemptionTestOnce(
- packageName, uid, pid, serviceType, sleepMs, stopAfterSleep,
+ packageName, uid, pid, serviceType, sleepMs, stopAfterSleep, withNotification,
perm, mediaControllers, topStateChanges, resetFGSTracker, false,
() -> {
clearInvocations(mInjector.getAppStandbyInternal());
clearInvocations(mBgRestrictionController);
- runTestBgCurrentDrainMonitorOnce(listener, stats, uids, bg, fgs, fg, false,
- () -> {
+ runTestBgCurrentDrainMonitorOnce(listener, stats, uids, bg, fgs, fg, cached,
+ false, () -> {
doReturn(mCurrentTimeMillis).when(stats).getStatsStartTimestamp();
doReturn(mCurrentTimeMillis + windowMs)
.when(stats).getStatsEndTimestamp();
@@ -2180,30 +2255,33 @@
private void runTestBgCurrentDrainMonitorOnce(TestAppRestrictionLevelListener listener,
BatteryUsageStats stats, int[] uids, double[] bg, double[] fgs, double[] fg,
- RunnableWithException runnable) throws Exception {
- runTestBgCurrentDrainMonitorOnce(listener, stats, uids, bg, fgs, fg, true, runnable);
+ double[] cached, RunnableWithException runnable) throws Exception {
+ runTestBgCurrentDrainMonitorOnce(listener, stats, uids, bg, fgs, fg, cached, true,
+ runnable);
}
private void runTestBgCurrentDrainMonitorOnce(TestAppRestrictionLevelListener listener,
BatteryUsageStats stats, int[] uids, double[] bg, double[] fgs, double[] fg,
- boolean resetListener, RunnableWithException runnable) throws Exception {
+ double[] cached, boolean resetListener, RunnableWithException runnable)
+ throws Exception {
if (resetListener) {
listener.mLatchHolder[0] = new CountDownLatch(1);
}
- setUidBatteryConsumptions(stats, uids, bg, fgs, fg);
+ setUidBatteryConsumptions(stats, uids, bg, fgs, fg, cached);
runnable.run();
}
private void setUidBatteryConsumptions(BatteryUsageStats stats, int[] uids, double[] bg,
- double[] fgs, double[] fg) {
+ double[] fgs, double[] fg, double[] cached) {
ArrayList<UidBatteryConsumer> consumers = new ArrayList<>();
for (int i = 0; i < uids.length; i++) {
- consumers.add(mockUidBatteryConsumer(uids[i], bg[i], fgs[i], fg[i]));
+ consumers.add(mockUidBatteryConsumer(uids[i], bg[i], fgs[i], fg[i], cached[i]));
}
doReturn(consumers).when(stats).getUidBatteryConsumers();
}
- private UidBatteryConsumer mockUidBatteryConsumer(int uid, double bg, double fgs, double fg) {
+ private UidBatteryConsumer mockUidBatteryConsumer(int uid, double bg, double fgs, double fg,
+ double cached) {
UidBatteryConsumer uidConsumer = mock(UidBatteryConsumer.class);
doReturn(uid).when(uidConsumer).getUid();
doReturn(bg).when(uidConsumer).getConsumedPower(
@@ -2212,6 +2290,8 @@
eq(BATT_DIMENS[BATTERY_USAGE_INDEX_FOREGROUND_SERVICE]));
doReturn(fg).when(uidConsumer).getConsumedPower(
eq(BATT_DIMENS[BATTERY_USAGE_INDEX_FOREGROUND]));
+ doReturn(cached).when(uidConsumer).getConsumedPower(
+ eq(BATT_DIMENS[BATTERY_USAGE_INDEX_CACHED]));
return uidConsumer;
}
@@ -2512,7 +2592,7 @@
final LinkedList<UidStateEventWithBattery> result = new LinkedList<>();
for (int i = 0; i < isStart.length; i++) {
result.add(new UidStateEventWithBattery(isStart[i], timestamps[i],
- new ImmutableBatteryUsage(0.0d, 0.0d, batteryUsage[i], 0.0d), null));
+ new ImmutableBatteryUsage(0.0d, 0.0d, batteryUsage[i], 0.0d, 0.0d), null));
}
return result;
}
@@ -2748,6 +2828,11 @@
RoleManager getRoleManager() {
return BackgroundRestrictionTest.this.mRoleManager;
}
+
+ @Override
+ IAppOpsService getIAppOpsService() {
+ return BackgroundRestrictionTest.this.mIAppOpsService;
+ }
}
private class TestAppBatteryTrackerInjector extends TestBaseTrackerInjector<AppBatteryPolicy> {
diff --git a/services/tests/mockingservicestests/src/com/android/server/display/LocalDisplayAdapterTest.java b/services/tests/mockingservicestests/src/com/android/server/display/LocalDisplayAdapterTest.java
index 784f732..8d6269c 100644
--- a/services/tests/mockingservicestests/src/com/android/server/display/LocalDisplayAdapterTest.java
+++ b/services/tests/mockingservicestests/src/com/android/server/display/LocalDisplayAdapterTest.java
@@ -118,6 +118,7 @@
LocalServices.removeServiceForTest(LightsManager.class);
LocalServices.addService(LightsManager.class, mMockedLightsManager);
mInjector = new Injector();
+ when(mSurfaceControlProxy.getBootDisplayModeSupport()).thenReturn(true);
mAdapter = new LocalDisplayAdapter(mMockedSyncRoot, mMockedContext, mHandler,
mListener, mInjector);
spyOn(mAdapter);
@@ -904,7 +905,6 @@
.thenReturn(display.dynamicInfo);
when(mSurfaceControlProxy.getDesiredDisplayModeSpecs(display.token))
.thenReturn(display.desiredDisplayModeSpecs);
- when(mSurfaceControlProxy.getBootDisplayModeSupport()).thenReturn(true);
}
private void updateAvailableDisplays() {
diff --git a/services/tests/mockingservicestests/src/com/android/server/pm/BackgroundDexOptServiceUnitTest.java b/services/tests/mockingservicestests/src/com/android/server/pm/BackgroundDexOptServiceUnitTest.java
index 6f503c7..444db91 100644
--- a/services/tests/mockingservicestests/src/com/android/server/pm/BackgroundDexOptServiceUnitTest.java
+++ b/services/tests/mockingservicestests/src/com/android/server/pm/BackgroundDexOptServiceUnitTest.java
@@ -19,7 +19,9 @@
import static com.google.common.truth.Truth.assertThat;
import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.argThat;
import static org.mockito.Mockito.atLeastOnce;
+import static org.mockito.Mockito.inOrder;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.timeout;
import static org.mockito.Mockito.times;
@@ -36,23 +38,21 @@
import android.content.IntentFilter;
import android.os.HandlerThread;
import android.os.PowerManager;
-import android.util.ArraySet;
import com.android.server.LocalServices;
import com.android.server.PinnerService;
import com.android.server.pm.dex.DexManager;
-import com.android.server.pm.dex.DexoptOptions;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.ArgumentCaptor;
+import org.mockito.InOrder;
import org.mockito.Mock;
import org.mockito.junit.MockitoJUnitRunner;
import java.util.Arrays;
-import java.util.HashMap;
import java.util.List;
import java.util.concurrent.CountDownLatch;
import java.util.stream.Collectors;
@@ -66,9 +66,8 @@
private static final long TEST_WAIT_TIMEOUT_MS = 10_000;
- private static final ArraySet<String> DEFAULT_PACKAGE_LIST = new ArraySet<>(
- Arrays.asList("aaa", "bbb"));
- private static final ArraySet<String> EMPTY_PACKAGE_LIST = new ArraySet<>();
+ private static final List<String> DEFAULT_PACKAGE_LIST = List.of("aaa", "bbb");
+ private static final List<String> EMPTY_PACKAGE_LIST = List.of();
@Mock
private Context mContext;
@@ -116,9 +115,11 @@
when(mInjector.getDataDirStorageLowBytes()).thenReturn(STORAGE_LOW_BYTES);
when(mInjector.getDexOptThermalCutoff()).thenReturn(PowerManager.THERMAL_STATUS_CRITICAL);
when(mInjector.getCurrentThermalStatus()).thenReturn(PowerManager.THERMAL_STATUS_NONE);
+ when(mInjector.supportSecondaryDex()).thenReturn(true);
when(mDexOptHelper.getOptimizablePackages(any())).thenReturn(DEFAULT_PACKAGE_LIST);
when(mDexOptHelper.performDexOptWithStatus(any())).thenReturn(
PackageDexOptimizer.DEX_OPT_PERFORMED);
+ when(mDexOptHelper.performDexOpt(any())).thenReturn(true);
mService = new BackgroundDexOptService(mInjector);
}
@@ -418,26 +419,16 @@
verifyPerformDexOpt(DEFAULT_PACKAGE_LIST, totalJobRuns);
}
- private void verifyPerformDexOpt(ArraySet<String> pkgs, int expectedRuns) {
- ArgumentCaptor<DexoptOptions> dexOptOptions = ArgumentCaptor.forClass(DexoptOptions.class);
- verify(mDexOptHelper, atLeastOnce()).performDexOptWithStatus(dexOptOptions.capture());
- HashMap<String, Integer> primaryPkgs = new HashMap<>(); // K: pkg, V: dexopt runs left
- for (String pkg : pkgs) {
- primaryPkgs.put(pkg, expectedRuns);
- }
-
- for (DexoptOptions opt : dexOptOptions.getAllValues()) {
- assertThat(pkgs).contains(opt.getPackageName());
- assertThat(opt.isDexoptOnlySecondaryDex()).isFalse();
- Integer count = primaryPkgs.get(opt.getPackageName());
- assertThat(count).isNotNull();
- if (count == 1) {
- primaryPkgs.remove(opt.getPackageName());
- } else {
- primaryPkgs.put(opt.getPackageName(), count - 1);
+ private void verifyPerformDexOpt(List<String> pkgs, int expectedRuns) {
+ InOrder inOrder = inOrder(mDexOptHelper);
+ for (int i = 0; i < expectedRuns; i++) {
+ for (String pkg : pkgs) {
+ inOrder.verify(mDexOptHelper, times(1)).performDexOptWithStatus(argThat((option) ->
+ option.getPackageName().equals(pkg) && !option.isDexoptOnlySecondaryDex()));
+ inOrder.verify(mDexOptHelper, times(1)).performDexOpt(argThat((option) ->
+ option.getPackageName().equals(pkg) && option.isDexoptOnlySecondaryDex()));
}
}
- assertThat(primaryPkgs).isEmpty();
}
private static class StartAndWaitThread extends Thread {
diff --git a/services/tests/mockingservicestests/src/com/android/server/tare/AgentTest.java b/services/tests/mockingservicestests/src/com/android/server/tare/AgentTest.java
index 41d46f2..534d0a1 100644
--- a/services/tests/mockingservicestests/src/com/android/server/tare/AgentTest.java
+++ b/services/tests/mockingservicestests/src/com/android/server/tare/AgentTest.java
@@ -21,7 +21,6 @@
import static org.junit.Assert.assertEquals;
import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.when;
import android.app.AlarmManager;
import android.content.Context;
@@ -71,10 +70,10 @@
.strictness(Strictness.LENIENT)
.mockStatic(LocalServices.class)
.startMocking();
- when(mIrs.getContext()).thenReturn(mContext);
- when(mIrs.getCompleteEconomicPolicyLocked()).thenReturn(mEconomicPolicy);
- when(mIrs.getLock()).thenReturn(mIrs);
- when(mContext.getSystemService(Context.ALARM_SERVICE)).thenReturn(mock(AlarmManager.class));
+ doReturn(mContext).when(mIrs).getContext();
+ doReturn(mEconomicPolicy).when(mIrs).getCompleteEconomicPolicyLocked();
+ doReturn(mIrs).when(mIrs).getLock();
+ doReturn(mock(AlarmManager.class)).when(mContext).getSystemService(Context.ALARM_SERVICE);
mScribe = new MockScribe(mIrs);
}
diff --git a/services/tests/mockingservicestests/src/com/android/server/utils/TimingsTraceAndSlogTest.java b/services/tests/mockingservicestests/src/com/android/server/utils/TimingsTraceAndSlogTest.java
new file mode 100644
index 0000000..52cd29c
--- /dev/null
+++ b/services/tests/mockingservicestests/src/com/android/server/utils/TimingsTraceAndSlogTest.java
@@ -0,0 +1,165 @@
+/*
+ * 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.utils;
+
+import static android.os.Trace.TRACE_TAG_APP;
+
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.mockitoSession;
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.verify;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.mockito.Matchers.anyString;
+import static org.mockito.Matchers.contains;
+import static org.mockito.Matchers.eq;
+import static org.mockito.Matchers.matches;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.times;
+
+import android.os.Trace;
+import android.util.Slog;
+
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
+
+import com.android.dx.mockito.inline.extended.MockedVoidMethod;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.MockitoSession;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Tests for {@link TimingsTraceAndSlog}.
+ *
+ * <p>Usage: {@code atest FrameworksMockingServicesTests:TimingsTraceAndSlogTest}
+ */
+@SmallTest
+@RunWith(AndroidJUnit4.class)
+public class TimingsTraceAndSlogTest {
+
+ private static final String TAG = "TEST";
+
+ private MockitoSession mSession;
+
+ @Before
+ public final void startMockSession() {
+ mSession = mockitoSession()
+ .spyStatic(Slog.class)
+ .spyStatic(Trace.class)
+ .startMocking();
+ }
+
+ @After
+ public final void finishMockSession() {
+ mSession.finishMocking();
+ }
+
+ @Test
+ public void testDifferentThreads() throws Exception {
+ TimingsTraceAndSlog log = new TimingsTraceAndSlog(TAG, TRACE_TAG_APP);
+ // Should be able to log on the same thread
+ log.traceBegin("test");
+ log.traceEnd();
+ final List<String> errors = new ArrayList<>();
+ // Calling from a different thread should fail
+ Thread t = new Thread(() -> {
+ try {
+ log.traceBegin("test");
+ errors.add("traceBegin should fail on a different thread");
+ } catch (IllegalStateException expected) {
+ }
+ try {
+ log.traceEnd();
+ errors.add("traceEnd should fail on a different thread");
+ } catch (IllegalStateException expected) {
+ }
+ // Verify that creating a new log will work
+ TimingsTraceAndSlog log2 = new TimingsTraceAndSlog(TAG, TRACE_TAG_APP);
+ log2.traceBegin("test");
+ log2.traceEnd();
+
+ });
+ t.start();
+ t.join();
+ assertThat(errors).isEmpty();
+ }
+
+ @Test
+ public void testGetUnfinishedTracesForDebug() {
+ TimingsTraceAndSlog log = new TimingsTraceAndSlog(TAG, TRACE_TAG_APP);
+ assertThat(log.getUnfinishedTracesForDebug()).isEmpty();
+
+ log.traceBegin("One");
+ assertThat(log.getUnfinishedTracesForDebug()).containsExactly("One").inOrder();
+
+ log.traceBegin("Two");
+ assertThat(log.getUnfinishedTracesForDebug()).containsExactly("One", "Two").inOrder();
+
+ log.traceEnd();
+ assertThat(log.getUnfinishedTracesForDebug()).containsExactly("One").inOrder();
+
+ log.traceEnd();
+ assertThat(log.getUnfinishedTracesForDebug()).isEmpty();
+ }
+
+ @Test
+ public void testLogDuration() throws Exception {
+ TimingsTraceAndSlog log = new TimingsTraceAndSlog(TAG, TRACE_TAG_APP);
+ log.logDuration("logro", 42);
+ verify((MockedVoidMethod) () -> Slog.v(eq(TAG), contains("logro took to complete: 42ms")));
+ }
+
+ @Test
+ public void testOneLevel() throws Exception {
+ TimingsTraceAndSlog log = new TimingsTraceAndSlog(TAG, TRACE_TAG_APP);
+ log.traceBegin("test");
+ log.traceEnd();
+
+ verify((MockedVoidMethod) () -> Trace.traceBegin(TRACE_TAG_APP, "test"));
+ verify((MockedVoidMethod) () -> Trace.traceEnd(TRACE_TAG_APP));
+ verify((MockedVoidMethod) () -> Slog.v(eq(TAG), matches("test took to complete: \\dms")));
+ }
+
+ @Test
+ public void testMultipleLevels() throws Exception {
+ TimingsTraceAndSlog log = new TimingsTraceAndSlog(TAG, TRACE_TAG_APP);
+ log.traceBegin("L1");
+ log.traceBegin("L2");
+ log.traceEnd();
+ log.traceEnd();
+
+ verify((MockedVoidMethod) () -> Trace.traceBegin(TRACE_TAG_APP, "L1"));
+ verify((MockedVoidMethod) () -> Trace.traceBegin(TRACE_TAG_APP, "L2"));
+ verify((MockedVoidMethod) () -> Trace.traceEnd(TRACE_TAG_APP), times(2)); // L1 and L2
+
+ verify((MockedVoidMethod) () -> Slog.v(eq(TAG), matches("L2 took to complete: \\d+ms")));
+ verify((MockedVoidMethod) () -> Slog.v(eq(TAG), matches("L1 took to complete: \\d+ms")));
+ }
+
+ @Test
+ public void testEndNoBegin() throws Exception {
+ TimingsTraceAndSlog log = new TimingsTraceAndSlog(TAG, TRACE_TAG_APP);
+ log.traceEnd();
+ verify((MockedVoidMethod) () -> Trace.traceEnd(TRACE_TAG_APP));
+ verify((MockedVoidMethod) () -> Slog.d(eq(TAG), anyString()), never());
+ verify((MockedVoidMethod) () -> Slog.w(TAG, "traceEnd called more times than traceBegin"));
+ }
+}
diff --git a/services/tests/servicestests/Android.bp b/services/tests/servicestests/Android.bp
index 152f3b3..e3be3a7 100644
--- a/services/tests/servicestests/Android.bp
+++ b/services/tests/servicestests/Android.bp
@@ -64,6 +64,7 @@
"testng",
"junit",
"platform-compat-test-rules",
+ "ActivityContext",
],
aidl: {
diff --git a/services/tests/servicestests/src/com/android/server/accessibility/AccessibilityManagerServiceTest.java b/services/tests/servicestests/src/com/android/server/accessibility/AccessibilityManagerServiceTest.java
index 1f016fb..56c5150 100644
--- a/services/tests/servicestests/src/com/android/server/accessibility/AccessibilityManagerServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/accessibility/AccessibilityManagerServiceTest.java
@@ -28,6 +28,8 @@
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.atLeastOnce;
+import static org.mockito.Mockito.doCallRealMethod;
import static org.mockito.Mockito.doThrow;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
@@ -61,10 +63,12 @@
import androidx.test.filters.SmallTest;
import com.android.compatibility.common.util.TestUtils;
+import com.android.internal.compat.IPlatformCompat;
import com.android.server.LocalServices;
import com.android.server.accessibility.AccessibilityManagerService.AccessibilityDisplayListener;
import com.android.server.accessibility.magnification.FullScreenMagnificationController;
import com.android.server.accessibility.magnification.MagnificationController;
+import com.android.server.accessibility.magnification.MagnificationProcessor;
import com.android.server.accessibility.magnification.WindowMagnificationManager;
import com.android.server.accessibility.test.MessageCapturingHandler;
import com.android.server.pm.UserManagerInternal;
@@ -185,7 +189,7 @@
mA11yms.mUserStates.put(mA11yms.getCurrentUserIdLocked(), userState);
}
- private void setupAccessibilityServiceConnection() {
+ private void setupAccessibilityServiceConnection(int serviceInfoFlag) {
final AccessibilityUserState userState = mA11yms.mUserStates.get(
mA11yms.getCurrentUserIdLocked());
when(mMockServiceInfo.getResolveInfo()).thenReturn(mMockResolveInfo);
@@ -193,7 +197,12 @@
mMockResolveInfo.serviceInfo.applicationInfo = mock(ApplicationInfo.class);
when(mMockBinder.queryLocalInterface(any())).thenReturn(mMockServiceClient);
+ when(mMockSystemSupport.getKeyEventDispatcher()).thenReturn(mock(KeyEventDispatcher.class));
+ when(mMockSystemSupport.getMagnificationProcessor()).thenReturn(
+ mock(MagnificationProcessor.class));
mTestableContext.addMockService(COMPONENT_NAME, mMockBinder);
+
+ mMockServiceInfo.flags = serviceInfoFlag;
mAccessibilityServiceConnection = new AccessibilityServiceConnection(
userState,
mTestableContext,
@@ -256,7 +265,7 @@
@SmallTest
@Test
public void testOnSystemActionsChanged() throws Exception {
- setupAccessibilityServiceConnection();
+ setupAccessibilityServiceConnection(0);
final AccessibilityUserState userState = mA11yms.mUserStates.get(
mA11yms.getCurrentUserIdLocked());
@@ -376,7 +385,7 @@
@SmallTest
@Test
public void testOnClientChange_boundServiceCanControlMagnification_requestConnection() {
- setupAccessibilityServiceConnection();
+ setupAccessibilityServiceConnection(0);
when(mMockSecurityPolicy.canControlMagnification(any())).thenReturn(true);
// Invokes client change to trigger onUserStateChanged.
@@ -385,6 +394,29 @@
verify(mMockWindowMagnificationMgr).requestConnection(true);
}
+ @Test
+ public void testUnbindIme_whenServiceUnbinds() {
+ setupAccessibilityServiceConnection(AccessibilityServiceInfo.FLAG_INPUT_METHOD_EDITOR);
+ mAccessibilityServiceConnection.unbindLocked();
+ verify(mMockSystemSupport, atLeastOnce()).unbindImeLocked(mAccessibilityServiceConnection);
+ }
+
+ @Test
+ public void testUnbindIme_whenServiceCrashed() {
+ setupAccessibilityServiceConnection(AccessibilityServiceInfo.FLAG_INPUT_METHOD_EDITOR);
+ mAccessibilityServiceConnection.binderDied();
+ verify(mMockSystemSupport).unbindImeLocked(mAccessibilityServiceConnection);
+ }
+
+ @Test
+ public void testUnbindIme_whenServiceStopsRequestingIme() {
+ setupAccessibilityServiceConnection(AccessibilityServiceInfo.FLAG_INPUT_METHOD_EDITOR);
+ doCallRealMethod().when(mMockServiceInfo).updateDynamicallyConfigurableProperties(
+ any(IPlatformCompat.class), any(AccessibilityServiceInfo.class));
+ mAccessibilityServiceConnection.setServiceInfo(new AccessibilityServiceInfo());
+ verify(mMockSystemSupport).unbindImeLocked(mAccessibilityServiceConnection);
+ }
+
public static class FakeInputFilter extends AccessibilityInputFilter {
FakeInputFilter(Context context,
AccessibilityManagerService service) {
diff --git a/services/tests/servicestests/src/com/android/server/accessibility/magnification/FullScreenMagnificationControllerTest.java b/services/tests/servicestests/src/com/android/server/accessibility/magnification/FullScreenMagnificationControllerTest.java
index f3a0b7f..0780d21 100644
--- a/services/tests/servicestests/src/com/android/server/accessibility/magnification/FullScreenMagnificationControllerTest.java
+++ b/services/tests/servicestests/src/com/android/server/accessibility/magnification/FullScreenMagnificationControllerTest.java
@@ -28,6 +28,7 @@
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;
@@ -45,13 +46,16 @@
import android.graphics.PointF;
import android.graphics.Rect;
import android.graphics.Region;
+import android.hardware.display.DisplayManagerInternal;
import android.os.Looper;
+import android.view.DisplayInfo;
import android.view.MagnificationSpec;
import android.view.accessibility.MagnificationAnimationCallback;
import androidx.test.InstrumentationRegistry;
import androidx.test.runner.AndroidJUnit4;
+import com.android.server.LocalServices;
import com.android.server.accessibility.AccessibilityTraceManager;
import com.android.server.accessibility.test.MessageCapturingHandler;
import com.android.server.wm.WindowManagerInternal;
@@ -113,6 +117,8 @@
FullScreenMagnificationController mFullScreenMagnificationController;
+ public DisplayManagerInternal mDisplayManagerInternalMock = mock(DisplayManagerInternal.class);
+
@Before
public void setUp() {
Looper looper = InstrumentationRegistry.getContext().getMainLooper();
@@ -125,6 +131,12 @@
when(mMockControllerCtx.getAnimationDuration()).thenReturn(1000L);
initMockWindowManager();
+ final DisplayInfo displayInfo = new DisplayInfo();
+ displayInfo.logicalDensityDpi = 300;
+ doReturn(displayInfo).when(mDisplayManagerInternalMock).getDisplayInfo(anyInt());
+ LocalServices.removeServiceForTest(DisplayManagerInternal.class);
+ LocalServices.addService(DisplayManagerInternal.class, mDisplayManagerInternalMock);
+
mFullScreenMagnificationController = new FullScreenMagnificationController(
mMockControllerCtx, new Object(), mRequestObserver, mScaleProvider);
}
diff --git a/services/tests/servicestests/src/com/android/server/biometrics/sensors/BiometricSchedulerOperationTest.java b/services/tests/servicestests/src/com/android/server/biometrics/sensors/BiometricSchedulerOperationTest.java
index eab96c0..c173473 100644
--- a/services/tests/servicestests/src/com/android/server/biometrics/sensors/BiometricSchedulerOperationTest.java
+++ b/services/tests/servicestests/src/com/android/server/biometrics/sensors/BiometricSchedulerOperationTest.java
@@ -72,9 +72,11 @@
@Mock
private ClientMonitorCallback mClientCallback;
@Mock
+ private ClientMonitorCallback mOnStartCallback;
+ @Mock
private FakeHal mHal;
@Captor
- ArgumentCaptor<ClientMonitorCallback> mStartCallback;
+ ArgumentCaptor<ClientMonitorCallback> mStartedCallbackCaptor;
private Handler mHandler;
private BiometricSchedulerOperation mOperation;
@@ -91,17 +93,17 @@
when(mClientMonitor.getCookie()).thenReturn(cookie);
when(mClientMonitor.getFreshDaemon()).thenReturn(mHal);
- assertThat(mOperation.isReadyToStart()).isEqualTo(cookie);
+ assertThat(mOperation.isReadyToStart(mOnStartCallback)).isEqualTo(cookie);
assertThat(mOperation.isStarted()).isFalse();
assertThat(mOperation.isCanceling()).isFalse();
assertThat(mOperation.isFinished()).isFalse();
+ verify(mClientMonitor).waitForCookie(any());
- final boolean started = mOperation.startWithCookie(
- mock(ClientMonitorCallback.class), cookie);
+ final boolean started = mOperation.startWithCookie(mOnStartCallback, cookie);
assertThat(started).isTrue();
- verify(mClientMonitor).start(mStartCallback.capture());
- mStartCallback.getValue().onClientStarted(mClientMonitor);
+ verify(mClientMonitor).start(mStartedCallbackCaptor.capture());
+ mStartedCallbackCaptor.getValue().onClientStarted(mClientMonitor);
assertThat(mOperation.isStarted()).isTrue();
}
@@ -112,14 +114,15 @@
when(mClientMonitor.getCookie()).thenReturn(goodCookie);
when(mClientMonitor.getFreshDaemon()).thenReturn(mHal);
- assertThat(mOperation.isReadyToStart()).isEqualTo(goodCookie);
- final boolean started = mOperation.startWithCookie(
- mock(ClientMonitorCallback.class), badCookie);
+ assertThat(mOperation.isReadyToStart(mOnStartCallback)).isEqualTo(goodCookie);
+ final boolean started = mOperation.startWithCookie(mOnStartCallback, badCookie);
assertThat(started).isFalse();
assertThat(mOperation.isStarted()).isFalse();
assertThat(mOperation.isCanceling()).isFalse();
assertThat(mOperation.isFinished()).isFalse();
+ verify(mClientMonitor).waitForCookie(any());
+ verify(mClientMonitor, never()).start(any());
}
@Test
@@ -127,26 +130,25 @@
when(mClientMonitor.getCookie()).thenReturn(0);
when(mClientMonitor.getFreshDaemon()).thenReturn(mHal);
- final ClientMonitorCallback cb = mock(ClientMonitorCallback.class);
- mOperation.start(cb);
- verify(mClientMonitor).start(mStartCallback.capture());
- mStartCallback.getValue().onClientStarted(mClientMonitor);
+ mOperation.start(mOnStartCallback);
+ verify(mClientMonitor).start(mStartedCallbackCaptor.capture());
+ mStartedCallbackCaptor.getValue().onClientStarted(mClientMonitor);
assertThat(mOperation.isStarted()).isTrue();
assertThat(mOperation.isCanceling()).isFalse();
assertThat(mOperation.isFinished()).isFalse();
verify(mClientCallback).onClientStarted(eq(mClientMonitor));
- verify(cb).onClientStarted(eq(mClientMonitor));
+ verify(mOnStartCallback).onClientStarted(eq(mClientMonitor));
verify(mClientCallback, never()).onClientFinished(any(), anyBoolean());
- verify(cb, never()).onClientFinished(any(), anyBoolean());
+ verify(mOnStartCallback, never()).onClientFinished(any(), anyBoolean());
- mStartCallback.getValue().onClientFinished(mClientMonitor, true);
+ mStartedCallbackCaptor.getValue().onClientFinished(mClientMonitor, true);
assertThat(mOperation.isFinished()).isTrue();
assertThat(mOperation.isCanceling()).isFalse();
verify(mClientMonitor).destroy();
- verify(cb).onClientFinished(eq(mClientMonitor), eq(true));
+ verify(mOnStartCallback).onClientFinished(eq(mClientMonitor), eq(true));
}
@Test
@@ -154,8 +156,7 @@
when(mClientMonitor.getCookie()).thenReturn(0);
when(mClientMonitor.getFreshDaemon()).thenReturn(null);
- final ClientMonitorCallback cb = mock(ClientMonitorCallback.class);
- mOperation.start(cb);
+ mOperation.start(mOnStartCallback);
verify(mClientMonitor, never()).start(any());
assertThat(mOperation.isStarted()).isFalse();
@@ -163,9 +164,9 @@
assertThat(mOperation.isFinished()).isTrue();
verify(mClientCallback, never()).onClientStarted(eq(mClientMonitor));
- verify(cb, never()).onClientStarted(eq(mClientMonitor));
+ verify(mOnStartCallback, never()).onClientStarted(eq(mClientMonitor));
verify(mClientCallback).onClientFinished(eq(mClientMonitor), eq(false));
- verify(cb).onClientFinished(eq(mClientMonitor), eq(false));
+ verify(mOnStartCallback).onClientFinished(eq(mClientMonitor), eq(false));
}
@Test
@@ -179,7 +180,7 @@
public void cannotRestart() {
when(mClientMonitor.getFreshDaemon()).thenReturn(mHal);
- mOperation.start(mock(ClientMonitorCallback.class));
+ mOperation.start(mOnStartCallback);
assertThrows(IllegalStateException.class,
() -> mOperation.start(mock(ClientMonitorCallback.class)));
@@ -202,7 +203,7 @@
public void cannotAbortRunning() {
when(mClientMonitor.getFreshDaemon()).thenReturn(mHal);
- mOperation.start(mock(ClientMonitorCallback.class));
+ mOperation.start(mOnStartCallback);
assertThrows(IllegalStateException.class, () -> mOperation.abort());
}
@@ -211,11 +212,10 @@
public void cancel() {
when(mClientMonitor.getFreshDaemon()).thenReturn(mHal);
- final ClientMonitorCallback startCb = mock(ClientMonitorCallback.class);
final ClientMonitorCallback cancelCb = mock(ClientMonitorCallback.class);
- mOperation.start(startCb);
- verify(mClientMonitor).start(mStartCallback.capture());
- mStartCallback.getValue().onClientStarted(mClientMonitor);
+ mOperation.start(mOnStartCallback);
+ verify(mClientMonitor).start(mStartedCallbackCaptor.capture());
+ mStartedCallbackCaptor.getValue().onClientStarted(mClientMonitor);
mOperation.cancel(mHandler, cancelCb);
assertThat(mOperation.isCanceling()).isTrue();
@@ -223,7 +223,7 @@
verify(mClientMonitor, never()).cancelWithoutStarting(any());
verify(mClientMonitor, never()).destroy();
- mStartCallback.getValue().onClientFinished(mClientMonitor, true);
+ mStartedCallbackCaptor.getValue().onClientFinished(mClientMonitor, true);
assertThat(mOperation.isFinished()).isTrue();
assertThat(mOperation.isCanceling()).isFalse();
@@ -315,12 +315,10 @@
private void cancelWatchdog(boolean start) {
when(mClientMonitor.getFreshDaemon()).thenReturn(mHal);
- final ClientMonitorCallback opStartCallback = mock(ClientMonitorCallback.class);
- mOperation.start(opStartCallback);
+ mOperation.start(mOnStartCallback);
if (start) {
- verify(mClientMonitor).start(mStartCallback.capture());
- mStartCallback.getValue().onClientStarted(mClientMonitor);
- verify(opStartCallback).onClientStarted(eq(mClientMonitor));
+ verify(mClientMonitor).start(mStartedCallbackCaptor.capture());
+ mStartedCallbackCaptor.getValue().onClientStarted(mClientMonitor);
}
mOperation.cancel(mHandler, mock(ClientMonitorCallback.class));
@@ -331,7 +329,7 @@
assertThat(mOperation.isFinished()).isTrue();
assertThat(mOperation.isCanceling()).isFalse();
- verify(opStartCallback).onClientFinished(eq(mClientMonitor), eq(false));
+ verify(mOnStartCallback).onClientFinished(eq(mClientMonitor), eq(false));
verify(mClientMonitor).destroy();
}
}
diff --git a/services/tests/servicestests/src/com/android/server/biometrics/sensors/BiometricSchedulerTest.java b/services/tests/servicestests/src/com/android/server/biometrics/sensors/BiometricSchedulerTest.java
index 0fa2b41..45e3b43 100644
--- a/services/tests/servicestests/src/com/android/server/biometrics/sensors/BiometricSchedulerTest.java
+++ b/services/tests/servicestests/src/com/android/server/biometrics/sensors/BiometricSchedulerTest.java
@@ -196,7 +196,8 @@
// Schedule a BiometricPrompt authentication request
mScheduler.scheduleClientMonitor(client1, callback1);
- assertNotEquals(0, mScheduler.mCurrentOperation.isReadyToStart());
+ assertNotEquals(0, mScheduler.mCurrentOperation.isReadyToStart(
+ mock(ClientMonitorCallback.class)));
assertEquals(client1, mScheduler.mCurrentOperation.getClientMonitor());
assertEquals(0, mScheduler.mPendingOperations.size());
@@ -436,7 +437,8 @@
if (started || isEnroll) { // prep'd auth clients and enroll clients
assertTrue(mScheduler.mCurrentOperation.isStarted());
} else {
- assertNotEquals(0, mScheduler.mCurrentOperation.isReadyToStart());
+ assertNotEquals(0, mScheduler.mCurrentOperation.isReadyToStart(
+ mock(ClientMonitorCallback.class)));
}
}
}
diff --git a/services/tests/servicestests/src/com/android/server/biometrics/sensors/SensorOverlaysTest.java b/services/tests/servicestests/src/com/android/server/biometrics/sensors/SensorOverlaysTest.java
index dc39b6d..5012335 100644
--- a/services/tests/servicestests/src/com/android/server/biometrics/sensors/SensorOverlaysTest.java
+++ b/services/tests/servicestests/src/com/android/server/biometrics/sensors/SensorOverlaysTest.java
@@ -21,6 +21,7 @@
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
import android.hardware.biometrics.BiometricOverlayConstants;
import android.hardware.fingerprint.ISidefpsController;
@@ -29,6 +30,7 @@
import androidx.test.filters.SmallTest;
+import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.mockito.Mock;
@@ -43,6 +45,7 @@
public class SensorOverlaysTest {
private static final int SENSOR_ID = 11;
+ private static final long REQUEST_ID = 8;
@Rule public final MockitoRule mockito = MockitoJUnit.rule();
@@ -50,6 +53,12 @@
@Mock private ISidefpsController mSidefpsController;
@Mock private AcquisitionClient<?> mAcquisitionClient;
+ @Before
+ public void setup() {
+ when(mAcquisitionClient.getRequestId()).thenReturn(REQUEST_ID);
+ when(mAcquisitionClient.hasRequestId()).thenReturn(true);
+ }
+
@Test
public void noopWhenBothNull() {
final SensorOverlays useless = new SensorOverlays(null, null);
@@ -92,7 +101,8 @@
sensorOverlays.show(SENSOR_ID, reason, mAcquisitionClient);
if (udfps != null) {
- verify(mUdfpsOverlayController).showUdfpsOverlay(eq(SENSOR_ID), eq(reason), any());
+ verify(mUdfpsOverlayController).showUdfpsOverlay(
+ eq(REQUEST_ID), eq(SENSOR_ID), eq(reason), any());
}
if (sidefps != null) {
verify(mSidefpsController).show(eq(SENSOR_ID), eq(reason));
diff --git a/services/tests/servicestests/src/com/android/server/biometrics/sensors/UserAwareBiometricSchedulerTest.java b/services/tests/servicestests/src/com/android/server/biometrics/sensors/UserAwareBiometricSchedulerTest.java
index 52eee9a..8391914 100644
--- a/services/tests/servicestests/src/com/android/server/biometrics/sensors/UserAwareBiometricSchedulerTest.java
+++ b/services/tests/servicestests/src/com/android/server/biometrics/sensors/UserAwareBiometricSchedulerTest.java
@@ -18,9 +18,8 @@
import static android.testing.TestableLooper.RunWithLooper;
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertNull;
-import static org.junit.Assert.assertSame;
+import static com.google.common.truth.Truth.assertThat;
+
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
@@ -45,11 +44,15 @@
import com.android.server.biometrics.log.BiometricLogger;
import org.junit.Before;
+import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
-import org.mockito.MockitoAnnotations;
+import org.mockito.junit.MockitoJUnit;
+import org.mockito.junit.MockitoRule;
+import java.util.ArrayList;
+import java.util.List;
import java.util.function.Supplier;
@Presubmit
@@ -61,9 +64,12 @@
private static final String TAG = "UserAwareBiometricSchedulerTest";
private static final int TEST_SENSOR_ID = 0;
+ @Rule
+ public final MockitoRule mockito = MockitoJUnit.rule();
+
private Handler mHandler;
private UserAwareBiometricScheduler mScheduler;
- private IBinder mToken = new Binder();
+ private final IBinder mToken = new Binder();
@Mock
private Context mContext;
@@ -74,15 +80,14 @@
@Mock
private BiometricContext mBiometricContext;
- private TestUserStartedCallback mUserStartedCallback = new TestUserStartedCallback();
- private TestUserStoppedCallback mUserStoppedCallback = new TestUserStoppedCallback();
+ private final TestUserStartedCallback mUserStartedCallback = new TestUserStartedCallback();
+ private final TestUserStoppedCallback mUserStoppedCallback = new TestUserStoppedCallback();
private int mCurrentUserId = UserHandle.USER_NULL;
private boolean mStartOperationsFinish = true;
private int mStartUserClientCount = 0;
@Before
public void setUp() {
- MockitoAnnotations.initMocks(this);
mHandler = new Handler(TestableLooper.get(this).getLooper());
mScheduler = new UserAwareBiometricScheduler(TAG,
mHandler,
@@ -121,8 +126,8 @@
mScheduler.scheduleClientMonitor(nextClient);
waitForIdle();
- assertEquals(0, mUserStoppedCallback.numInvocations);
- assertEquals(1, mUserStartedCallback.numInvocations);
+ assertThat(mUserStoppedCallback.mNumInvocations).isEqualTo(0);
+ assertThat(mUserStartedCallback.mStartedUsers).containsExactly(0);
verify(nextClient).start(any());
}
@@ -142,9 +147,9 @@
waitForIdle();
}
- assertEquals(0, mUserStoppedCallback.numInvocations);
- assertEquals(0, mUserStartedCallback.numInvocations);
- assertEquals(1, mStartUserClientCount);
+ assertThat(mUserStoppedCallback.mNumInvocations).isEqualTo(0);
+ assertThat(mUserStartedCallback.mStartedUsers).isEmpty();
+ assertThat(mStartUserClientCount).isEqualTo(1);
for (BaseClientMonitor client : nextClients) {
verify(client, never()).start(any());
}
@@ -163,13 +168,13 @@
final TestStartUserClient startUserClient =
(TestStartUserClient) mScheduler.mCurrentOperation.getClientMonitor();
mScheduler.reset();
- assertNull(mScheduler.mCurrentOperation);
+ assertThat(mScheduler.mCurrentOperation).isNull();
final BiometricSchedulerOperation fakeOperation = new BiometricSchedulerOperation(
mock(BaseClientMonitor.class), new ClientMonitorCallback() {});
mScheduler.mCurrentOperation = fakeOperation;
startUserClient.mCallback.onClientFinished(startUserClient, true);
- assertSame(fakeOperation, mScheduler.mCurrentOperation);
+ assertThat(fakeOperation).isSameInstanceAs(mScheduler.mCurrentOperation);
}
@Test
@@ -184,8 +189,8 @@
waitForIdle();
verify(nextClient).start(any());
- assertEquals(0, mUserStoppedCallback.numInvocations);
- assertEquals(0, mUserStartedCallback.numInvocations);
+ assertThat(mUserStoppedCallback.mNumInvocations).isEqualTo(0);
+ assertThat(mUserStartedCallback.mStartedUsers).isEmpty();
}
@Test
@@ -199,36 +204,67 @@
mScheduler.scheduleClientMonitor(nextClient);
waitForIdle();
- assertEquals(1, mUserStoppedCallback.numInvocations);
+ assertThat(mUserStoppedCallback.mNumInvocations).isEqualTo(1);
waitForIdle();
- assertEquals(1, mUserStartedCallback.numInvocations);
+ assertThat(mUserStartedCallback.mStartedUsers).containsExactly(nextUserId);
waitForIdle();
verify(nextClient).start(any());
}
+ @Test
+ public void testStartUser_alwaysStartsNextOperation() {
+ BaseClientMonitor nextClient = mock(BaseClientMonitor.class);
+ when(nextClient.getTargetUserId()).thenReturn(10);
+
+ mScheduler.scheduleClientMonitor(nextClient);
+
+ waitForIdle();
+ verify(nextClient).start(any());
+
+ // finish first operation
+ mScheduler.getInternalCallback().onClientFinished(nextClient, true /* success */);
+ waitForIdle();
+
+ // schedule second operation but swap out the current operation
+ // before it runs so that it's not current when it's completion callback runs
+ nextClient = mock(BaseClientMonitor.class);
+ when(nextClient.getTargetUserId()).thenReturn(11);
+ mUserStartedCallback.mAfterStart = () -> mScheduler.mCurrentOperation = null;
+ mScheduler.scheduleClientMonitor(nextClient);
+
+ waitForIdle();
+ verify(nextClient).start(any());
+ assertThat(mUserStartedCallback.mStartedUsers).containsExactly(10, 11).inOrder();
+ assertThat(mUserStoppedCallback.mNumInvocations).isEqualTo(1);
+ }
+
private void waitForIdle() {
TestableLooper.get(this).processAllMessages();
}
private class TestUserStoppedCallback implements StopUserClient.UserStoppedCallback {
- int numInvocations;
+ int mNumInvocations;
@Override
public void onUserStopped() {
- numInvocations++;
+ mNumInvocations++;
mCurrentUserId = UserHandle.USER_NULL;
}
}
private class TestUserStartedCallback implements StartUserClient.UserStartedCallback<Object> {
- int numInvocations;
+ final List<Integer> mStartedUsers = new ArrayList<>();
+ Runnable mAfterStart = null;
@Override
public void onUserStarted(int newUserId, Object newObject, int halInterfaceVersion) {
- numInvocations++;
+ mStartedUsers.add(newUserId);
mCurrentUserId = newUserId;
+ if (mAfterStart != null) {
+ mAfterStart.run();
+ }
}
}
diff --git a/services/tests/servicestests/src/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintAuthenticationClientTest.java b/services/tests/servicestests/src/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintAuthenticationClientTest.java
index de0f038..6c50ca3 100644
--- a/services/tests/servicestests/src/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintAuthenticationClientTest.java
+++ b/services/tests/servicestests/src/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintAuthenticationClientTest.java
@@ -71,6 +71,7 @@
private static final int USER_ID = 8;
private static final long OP_ID = 7;
+ private static final long REQUEST_ID = 88;
private static final int POINTER_ID = 0;
private static final int TOUCH_X = 8;
private static final int TOUCH_Y = 20;
@@ -259,7 +260,7 @@
client.start(mCallback);
- verify(mUdfpsOverlayController).showUdfpsOverlay(anyInt(), anyInt(), any());
+ verify(mUdfpsOverlayController).showUdfpsOverlay(eq(REQUEST_ID), anyInt(), anyInt(), any());
verify(mSideFpsController).show(anyInt(), anyInt());
block.accept(client);
@@ -277,7 +278,7 @@
final AidlSession aidl = new AidlSession(version, mHal, USER_ID, mHalSessionCallback);
return new FingerprintAuthenticationClient(mContext, () -> aidl, mToken,
- 2 /* requestId */, mClientMonitorCallbackConverter, 5 /* targetUserId */, OP_ID,
+ REQUEST_ID, mClientMonitorCallbackConverter, 5 /* targetUserId */, OP_ID,
false /* restricted */, "test-owner", 4 /* cookie */, false /* requireConfirmation */,
9 /* sensorId */, mBiometricLogger, mBiometricContext,
true /* isStrongBiometric */,
diff --git a/services/tests/servicestests/src/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintEnrollClientTest.java b/services/tests/servicestests/src/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintEnrollClientTest.java
index 5a96f5c..f77eb0b 100644
--- a/services/tests/servicestests/src/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintEnrollClientTest.java
+++ b/services/tests/servicestests/src/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintEnrollClientTest.java
@@ -72,6 +72,7 @@
private static final byte[] HAT = new byte[69];
private static final int USER_ID = 8;
+ private static final long REQUEST_ID = 9;
private static final int POINTER_ID = 0;
private static final int TOUCH_X = 8;
private static final int TOUCH_Y = 20;
@@ -256,7 +257,7 @@
client.start(mCallback);
- verify(mUdfpsOverlayController).showUdfpsOverlay(anyInt(), anyInt(), any());
+ verify(mUdfpsOverlayController).showUdfpsOverlay(eq(REQUEST_ID), anyInt(), anyInt(), any());
verify(mSideFpsController).show(anyInt(), anyInt());
block.accept(client);
@@ -273,7 +274,7 @@
when(mHal.getInterfaceVersion()).thenReturn(version);
final AidlSession aidl = new AidlSession(version, mHal, USER_ID, mHalSessionCallback);
- return new FingerprintEnrollClient(mContext, () -> aidl, mToken, 6 /* requestId */,
+ return new FingerprintEnrollClient(mContext, () -> aidl, mToken, REQUEST_ID,
mClientMonitorCallbackConverter, 0 /* userId */,
HAT, "owner", mBiometricUtils, 8 /* sensorId */,
mBiometricLogger, mBiometricContext, mSensorProps, mUdfpsOverlayController,
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 1ebcbe1..89bd10f 100644
--- a/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java
+++ b/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java
@@ -158,6 +158,7 @@
import org.hamcrest.Matcher;
import org.junit.After;
import org.junit.Before;
+import org.junit.Ignore;
import org.junit.Test;
import org.mockito.Mockito;
import org.mockito.internal.util.collections.Sets;
@@ -186,6 +187,7 @@
*/
@SmallTest
@Presubmit
+@Ignore("b/225415867")
public class DevicePolicyManagerTest extends DpmTestBase {
private static final String TAG = DevicePolicyManagerTest.class.getSimpleName();
@@ -4260,14 +4262,11 @@
dpm.setPreferentialNetworkServiceConfigs(List.of(preferentialNetworkServiceConfigEnabled));
assertThat(dpm.getPreferentialNetworkServiceConfigs().get(0)
.isEnabled()).isTrue();
- List<Integer> includedList = new ArrayList<>();
- includedList.add(1);
- includedList.add(2);
ProfileNetworkPreference preferenceDetails =
new ProfileNetworkPreference.Builder()
.setPreference(PROFILE_NETWORK_PREFERENCE_ENTERPRISE_NO_FALLBACK)
.setPreferenceEnterpriseId(NET_ENTERPRISE_ID_1)
- .setIncludedUids(includedList)
+ .setIncludedUids(new int[]{1, 2})
.build();
List<ProfileNetworkPreference> preferences = new ArrayList<>();
preferences.add(preferenceDetails);
@@ -4295,14 +4294,11 @@
dpm.setPreferentialNetworkServiceConfigs(List.of(preferentialNetworkServiceConfigEnabled));
assertThat(dpm.getPreferentialNetworkServiceConfigs().get(0)
.isEnabled()).isTrue();
- List<Integer> excludedUids = new ArrayList<>();
- excludedUids.add(1);
- excludedUids.add(2);
ProfileNetworkPreference preferenceDetails =
new ProfileNetworkPreference.Builder()
.setPreference(PROFILE_NETWORK_PREFERENCE_ENTERPRISE_NO_FALLBACK)
.setPreferenceEnterpriseId(NET_ENTERPRISE_ID_1)
- .setExcludedUids(excludedUids)
+ .setExcludedUids(new int[]{1, 2})
.build();
List<ProfileNetworkPreference> preferences = new ArrayList<>();
preferences.clear();
@@ -6671,7 +6667,7 @@
configureContextForAccess(mContext, false);
assertExpectException(SecurityException.class, /* messageRegex= */ null,
- () -> dpm.markProfileOwnerOnOrganizationOwnedDevice(admin2));
+ () -> dpm.setProfileOwnerOnOrganizationOwnedDevice(admin2, true));
}
@Test
@@ -6680,7 +6676,7 @@
configureContextForAccess(mContext, false);
assertExpectException(SecurityException.class, /* messageRegex= */ null,
- () -> dpm.markProfileOwnerOnOrganizationOwnedDevice(admin1));
+ () -> dpm.setProfileOwnerOnOrganizationOwnedDevice(admin1, true));
}
@Test
@@ -6715,7 +6711,7 @@
DpmMockContext.CALLER_MANAGED_PROVISIONING_UID);
try {
runAsCaller(mServiceContext, dpms, dpm -> {
- dpm.markProfileOwnerOnOrganizationOwnedDevice(admin1);
+ dpm.setProfileOwnerOnOrganizationOwnedDevice(admin1, true);
});
} finally {
mServiceContext.binder.restoreCallingIdentity(ident);
@@ -7050,7 +7046,7 @@
configureContextForAccess(mServiceContext, true);
runAsCaller(mServiceContext, dpms, dpm -> {
- dpm.markProfileOwnerOnOrganizationOwnedDevice(who);
+ dpm.setProfileOwnerOnOrganizationOwnedDevice(who, true);
});
mServiceContext.binder.restoreCallingIdentity(ident);
}
diff --git a/services/tests/servicestests/src/com/android/server/display/ColorFadeTest.java b/services/tests/servicestests/src/com/android/server/display/ColorFadeTest.java
new file mode 100644
index 0000000..26a83a2
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/display/ColorFadeTest.java
@@ -0,0 +1,75 @@
+/*
+ * 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 androidx.test.platform.app.InstrumentationRegistry.getInstrumentation;
+
+import static org.junit.Assert.assertFalse;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.when;
+
+import android.content.Context;
+import android.hardware.display.DisplayManagerInternal;
+import android.platform.test.annotations.Presubmit;
+
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
+
+import com.android.server.LocalServices;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+
+@SmallTest
+@Presubmit
+@RunWith(AndroidJUnit4.class)
+public class ColorFadeTest {
+ private static final int DISPLAY_ID = 123;
+
+ private Context mContext;
+
+ @Mock private DisplayManagerInternal mDisplayManagerInternalMock;
+
+ @Before
+ public void setUp() {
+ MockitoAnnotations.initMocks(this);
+ addLocalServiceMock(DisplayManagerInternal.class, mDisplayManagerInternalMock);
+ mContext = getInstrumentation().getTargetContext();
+ }
+
+ @After
+ public void tearDown() {
+ LocalServices.removeServiceForTest(DisplayManagerInternal.class);
+ }
+
+ @Test
+ public void testPrepareColorFadeForInvalidDisplay() {
+ when(mDisplayManagerInternalMock.getDisplayInfo(eq(DISPLAY_ID))).thenReturn(null);
+ ColorFade colorFade = new ColorFade(DISPLAY_ID);
+ assertFalse(colorFade.prepare(mContext, ColorFade.MODE_FADE));
+ }
+
+ private static <T> void addLocalServiceMock(Class<T> clazz, T mock) {
+ LocalServices.removeServiceForTest(clazz);
+ LocalServices.addService(clazz, mock);
+ }
+
+}
diff --git a/services/tests/servicestests/src/com/android/server/pm/CrossProfileAppsServiceImplTest.java b/services/tests/servicestests/src/com/android/server/pm/CrossProfileAppsServiceImplTest.java
index 3cb5d5f..ce322f7 100644
--- a/services/tests/servicestests/src/com/android/server/pm/CrossProfileAppsServiceImplTest.java
+++ b/services/tests/servicestests/src/com/android/server/pm/CrossProfileAppsServiceImplTest.java
@@ -20,6 +20,7 @@
import android.Manifest;
import android.app.ActivityManager;
import android.app.ActivityManagerInternal;
+import android.app.ActivityOptions;
import android.app.AppOpsManager;
import android.app.IApplicationThread;
import android.app.admin.DevicePolicyManagerInternal;
@@ -46,6 +47,7 @@
import android.platform.test.annotations.Presubmit;
import android.util.SparseArray;
+import com.android.activitycontext.ActivityContext;
import com.android.internal.util.FunctionalUtils.ThrowingRunnable;
import com.android.internal.util.FunctionalUtils.ThrowingSupplier;
import com.android.server.LocalServices;
@@ -240,7 +242,9 @@
FEATURE_ID,
ACTIVITY_COMPONENT,
UserHandle.of(PRIMARY_USER).getIdentifier(),
- true));
+ true,
+ /* targetTask */ null,
+ /* options */ null));
verify(mActivityTaskManagerInternal, never())
.startActivityAsUser(
@@ -265,7 +269,9 @@
FEATURE_ID,
ACTIVITY_COMPONENT,
UserHandle.of(PRIMARY_USER).getIdentifier(),
- false));
+ false,
+ /* targetTask */ null,
+ /* options */ null));
verify(mActivityTaskManagerInternal, never())
.startActivityAsUser(
@@ -292,7 +298,9 @@
FEATURE_ID,
ACTIVITY_COMPONENT,
UserHandle.of(PROFILE_OF_PRIMARY_USER).getIdentifier(),
- true));
+ true,
+ /* targetTask */ null,
+ /* options */ null));
verify(mActivityTaskManagerInternal, never())
.startActivityAsUser(
@@ -319,7 +327,9 @@
FEATURE_ID,
ACTIVITY_COMPONENT,
UserHandle.of(PROFILE_OF_PRIMARY_USER).getIdentifier(),
- false));
+ false,
+ /* targetTask */ null,
+ /* options */ null));
verify(mActivityTaskManagerInternal, never())
.startActivityAsUser(
@@ -344,7 +354,9 @@
FEATURE_ID,
ACTIVITY_COMPONENT,
UserHandle.of(PROFILE_OF_PRIMARY_USER).getIdentifier(),
- true));
+ true,
+ /* targetTask */ null,
+ /* options */ null));
verify(mActivityTaskManagerInternal, never())
.startActivityAsUser(
@@ -369,7 +381,9 @@
FEATURE_ID,
ACTIVITY_COMPONENT,
UserHandle.of(PROFILE_OF_PRIMARY_USER).getIdentifier(),
- false));
+ false,
+ /* targetTask */ null,
+ /* options */ null));
verify(mActivityTaskManagerInternal, never())
.startActivityAsUser(
@@ -396,7 +410,9 @@
FEATURE_ID,
ACTIVITY_COMPONENT,
UserHandle.of(PROFILE_OF_PRIMARY_USER).getIdentifier(),
- true));
+ true,
+ /* targetTask */ null,
+ /* options */ null));
verify(mActivityTaskManagerInternal, never())
.startActivityAsUser(
@@ -440,7 +456,9 @@
FEATURE_ID,
ACTIVITY_COMPONENT,
UserHandle.of(PROFILE_OF_PRIMARY_USER).getIdentifier(),
- false));
+ false,
+ /* targetTask */ null,
+ /* options */ null));
verify(mActivityTaskManagerInternal, never())
.startActivityAsUser(
@@ -465,7 +483,9 @@
FEATURE_ID,
new ComponentName(PACKAGE_TWO, "test"),
UserHandle.of(PROFILE_OF_PRIMARY_USER).getIdentifier(),
- true));
+ true,
+ /* targetTask */ null,
+ /* options */ null));
verify(mActivityTaskManagerInternal, never())
.startActivityAsUser(
@@ -490,7 +510,9 @@
FEATURE_ID,
new ComponentName(PACKAGE_TWO, "test"),
UserHandle.of(PROFILE_OF_PRIMARY_USER).getIdentifier(),
- false));
+ false,
+ /* targetTask */ null,
+ /* options */ null));
verify(mActivityTaskManagerInternal, never())
.startActivityAsUser(
@@ -515,7 +537,9 @@
FEATURE_ID,
ACTIVITY_COMPONENT,
UserHandle.of(SECONDARY_USER).getIdentifier(),
- true));
+ true,
+ /* targetTask */ null,
+ /* options */ null));
verify(mActivityTaskManagerInternal, never())
.startActivityAsUser(
@@ -540,7 +564,9 @@
FEATURE_ID,
ACTIVITY_COMPONENT,
UserHandle.of(SECONDARY_USER).getIdentifier(),
- false));
+ false,
+ /* targetTask */ null,
+ /* options */ null));
verify(mActivityTaskManagerInternal, never())
.startActivityAsUser(
@@ -564,7 +590,9 @@
FEATURE_ID,
ACTIVITY_COMPONENT,
UserHandle.of(PRIMARY_USER).getIdentifier(),
- true);
+ true,
+ /* targetTask */ null,
+ /* options */ null);
verify(mActivityTaskManagerInternal)
.startActivityAsUser(
@@ -578,6 +606,44 @@
eq(PRIMARY_USER));
}
+ @Test
+ public void startActivityAsUser_sameTask_fromProfile_success() throws Exception {
+ mTestInjector.setCallingUserId(PROFILE_OF_PRIMARY_USER);
+
+ Bundle options = ActivityOptions.makeOpenCrossProfileAppsAnimation().toBundle();
+ IBinder result = ActivityContext.getWithContext(activity -> {
+ try {
+ IBinder targetTask = activity.getActivityToken();
+ mCrossProfileAppsServiceImpl.startActivityAsUser(
+ mIApplicationThread,
+ PACKAGE_ONE,
+ FEATURE_ID,
+ ACTIVITY_COMPONENT,
+ UserHandle.of(PRIMARY_USER).getIdentifier(),
+ true,
+ targetTask,
+ options);
+ return targetTask;
+ } catch (Exception re) {
+ return null;
+ }
+ });
+ if (result == null) {
+ throw new Exception();
+ }
+
+ verify(mActivityTaskManagerInternal)
+ .startActivityAsUser(
+ nullable(IApplicationThread.class),
+ eq(PACKAGE_ONE),
+ eq(FEATURE_ID),
+ any(Intent.class),
+ eq(result),
+ anyInt(),
+ eq(options),
+ eq(PRIMARY_USER));
+ }
+
private void mockAppsInstalled(String packageName, int user, boolean installed) {
when(mPackageManagerInternal.getPackageInfo(
eq(packageName),
diff --git a/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest2.java b/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest2.java
index 99edecf..c786784 100644
--- a/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest2.java
+++ b/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest2.java
@@ -16,7 +16,6 @@
package com.android.server.pm;
import static com.android.server.pm.shortcutmanagertest.ShortcutManagerTestUtils.assertBundlesEqual;
-import static com.android.server.pm.shortcutmanagertest.ShortcutManagerTestUtils.assertEmpty;
import static com.android.server.pm.shortcutmanagertest.ShortcutManagerTestUtils.assertExpectException;
import static com.android.server.pm.shortcutmanagertest.ShortcutManagerTestUtils.assertWith;
import static com.android.server.pm.shortcutmanagertest.ShortcutManagerTestUtils.list;
@@ -37,6 +36,8 @@
import android.content.ComponentName;
import android.content.Intent;
import android.content.LocusId;
+import android.content.pm.Capability;
+import android.content.pm.CapabilityParams;
import android.content.pm.ShortcutInfo;
import android.content.res.Resources;
import android.graphics.BitmapFactory;
@@ -258,10 +259,15 @@
.setLongLived(true)
.setExtras(pb)
.setStartingTheme(android.R.style.Theme_Black_NoTitleBar_Fullscreen)
- .addCapabilityBinding("action.intent.START_EXERCISE",
- "exercise.type", list("running", "jogging"))
- .addCapabilityBinding("action.intent.START_EXERCISE",
- "exercise.duration", list("10m"))
+ .addCapabilityBinding(
+ new Capability.Builder("action.intent.START_EXERCISE").build(),
+ new CapabilityParams.Builder("exercise.type", "running")
+ .addAlias("jogging")
+ .build())
+ .addCapabilityBinding(
+ new Capability.Builder("action.intent.START_EXERCISE").build(),
+ new CapabilityParams.Builder("exercise.duration", "10m")
+ .build())
.build();
si.addFlags(ShortcutInfo.FLAG_PINNED);
si.setBitmapPath("abc");
@@ -299,13 +305,14 @@
assertEquals(null, si.getDisabledMessageResName());
assertEquals("android:style/Theme.Black.NoTitleBar.Fullscreen",
si.getStartingThemeResName());
- assertTrue(si.hasCapability("action.intent.START_EXERCISE"));
- assertFalse(si.hasCapability(""));
- assertFalse(si.hasCapability("random"));
- assertEquals(list("running", "jogging"), si.getCapabilityParameterValues(
- "action.intent.START_EXERCISE", "exercise.type"));
- assertEmpty(si.getCapabilityParameterValues("action.intent.START_EXERCISE", ""));
- assertEmpty(si.getCapabilityParameterValues("action.intent.START_EXERCISE", "random"));
+ assertEquals(list(new Capability.Builder("action.intent.START_EXERCISE").build()),
+ si.getCapabilities());
+ assertEquals(list(
+ new CapabilityParams.Builder("exercise.type", "running")
+ .addAlias("jogging").build(),
+ new CapabilityParams.Builder("exercise.duration", "10m").build()),
+ si.getCapabilityParams(
+ new Capability.Builder("action.intent.START_EXERCISE").build()));
}
public void testShortcutInfoParcel_resId() {
@@ -959,10 +966,15 @@
.setRank(123)
.setExtras(pb)
.setLocusId(new LocusId("1.2.3.4.5"))
- .addCapabilityBinding("action.intent.START_EXERCISE",
- "exercise.type", list("running", "jogging"))
- .addCapabilityBinding("action.intent.START_EXERCISE",
- "exercise.duration", list("10m"))
+ .addCapabilityBinding(
+ new Capability.Builder("action.intent.START_EXERCISE").build(),
+ new CapabilityParams.Builder("exercise.type", "running")
+ .addAlias("jogging")
+ .build())
+ .addCapabilityBinding(
+ new Capability.Builder("action.intent.START_EXERCISE").build(),
+ new CapabilityParams.Builder("exercise.duration", "10m")
+ .build())
.build();
sorig.setTimestamp(mInjectedCurrentTimeMillis);
@@ -1024,13 +1036,14 @@
assertNull(si.getIconUri());
assertTrue(si.getLastChangedTimestamp() < now);
- assertTrue(si.hasCapability("action.intent.START_EXERCISE"));
- assertFalse(si.hasCapability(""));
- assertFalse(si.hasCapability("random"));
- assertEquals(list("running", "jogging"), si.getCapabilityParameterValues(
- "action.intent.START_EXERCISE", "exercise.type"));
- assertEmpty(si.getCapabilityParameterValues("action.intent.START_EXERCISE", ""));
- assertEmpty(si.getCapabilityParameterValues("action.intent.START_EXERCISE", "random"));
+ assertEquals(list(new Capability.Builder("action.intent.START_EXERCISE").build()),
+ si.getCapabilities());
+ assertEquals(list(
+ new CapabilityParams.Builder("exercise.type", "running")
+ .addAlias("jogging").build(),
+ new CapabilityParams.Builder("exercise.duration", "10m").build()),
+ si.getCapabilityParams(
+ new Capability.Builder("action.intent.START_EXERCISE").build()));
// Make sure ranks are saved too. Because of the auto-adjusting, we need two shortcuts
// to test it.
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 c7b5547..06b7112 100644
--- a/services/tests/servicestests/src/com/android/server/pm/UserManagerTest.java
+++ b/services/tests/servicestests/src/com/android/server/pm/UserManagerTest.java
@@ -316,7 +316,8 @@
asHandle(currentUser));
try {
assertThat(mUserManager.removeUserWhenPossible(user1.getUserHandle(),
- /* overrideDevicePolicy= */ false)).isEqualTo(UserManager.REMOVE_RESULT_ERROR);
+ /* overrideDevicePolicy= */ false))
+ .isEqualTo(UserManager.REMOVE_RESULT_ERROR_USER_RESTRICTION);
} finally {
mUserManager.setUserRestriction(UserManager.DISALLOW_REMOVE_USER, /* value= */ false,
asHandle(currentUser));
@@ -353,7 +354,8 @@
@Test
public void testRemoveUserWhenPossible_systemUserReturnsError() throws Exception {
assertThat(mUserManager.removeUserWhenPossible(UserHandle.SYSTEM,
- /* overrideDevicePolicy= */ false)).isEqualTo(UserManager.REMOVE_RESULT_ERROR);
+ /* overrideDevicePolicy= */ false))
+ .isEqualTo(UserManager.REMOVE_RESULT_ERROR_SYSTEM_USER);
assertThat(hasUser(UserHandle.USER_SYSTEM)).isTrue();
}
@@ -363,7 +365,8 @@
public void testRemoveUserWhenPossible_invalidUserReturnsError() throws Exception {
assertThat(hasUser(Integer.MAX_VALUE)).isFalse();
assertThat(mUserManager.removeUserWhenPossible(UserHandle.of(Integer.MAX_VALUE),
- /* overrideDevicePolicy= */ false)).isEqualTo(UserManager.REMOVE_RESULT_ERROR);
+ /* overrideDevicePolicy= */ false))
+ .isEqualTo(UserManager.REMOVE_RESULT_ERROR_USER_NOT_FOUND);
}
@MediumTest
diff --git a/services/tests/servicestests/src/com/android/server/soundtrigger_middleware/SoundTriggerMiddlewareImplTest.java b/services/tests/servicestests/src/com/android/server/soundtrigger_middleware/SoundTriggerMiddlewareImplTest.java
index 0eba6a3..0187e34 100644
--- a/services/tests/servicestests/src/com/android/server/soundtrigger_middleware/SoundTriggerMiddlewareImplTest.java
+++ b/services/tests/servicestests/src/com/android/server/soundtrigger_middleware/SoundTriggerMiddlewareImplTest.java
@@ -224,6 +224,11 @@
// Stop the recognition.
stopRecognition(module, handle, hwHandle);
+ ArgumentCaptor<RecognitionEvent> eventCaptor = ArgumentCaptor.forClass(
+ RecognitionEvent.class);
+ verify(callback).onRecognition(eq(handle), eventCaptor.capture(), eq(101));
+ assertEquals(RecognitionStatus.ABORTED, eventCaptor.getValue().status);
+
// Unload the model.
unloadModel(module, handle, hwHandle);
module.detach();
@@ -268,6 +273,11 @@
// Stop the recognition.
stopRecognition(module, handle, hwHandle);
+ ArgumentCaptor<PhraseRecognitionEvent> eventCaptor = ArgumentCaptor.forClass(
+ PhraseRecognitionEvent.class);
+ verify(callback).onPhraseRecognition(eq(handle), eventCaptor.capture(), eq(101));
+ assertEquals(RecognitionStatus.ABORTED, eventCaptor.getValue().common.status);
+
// Unload the model.
unloadModel(module, handle, hwHandle);
module.detach();
diff --git a/services/tests/servicestests/src/com/android/server/statusbar/StatusBarManagerServiceTest.java b/services/tests/servicestests/src/com/android/server/statusbar/StatusBarManagerServiceTest.java
index d76a1de..83139b0 100644
--- a/services/tests/servicestests/src/com/android/server/statusbar/StatusBarManagerServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/statusbar/StatusBarManagerServiceTest.java
@@ -692,23 +692,12 @@
public void testSetNavBarMode_invalidInputThrowsError() throws RemoteException {
int navBarModeInvalid = -1;
- assertThrows(UnsupportedOperationException.class,
+ assertThrows(IllegalArgumentException.class,
() -> mStatusBarManagerService.setNavBarMode(navBarModeInvalid));
verify(mOverlayManager, never()).setEnabledExclusiveInCategory(anyString(), anyInt());
}
@Test
- public void testSetNavBarMode_noOverlayManagerDoesNotEnable() throws RemoteException {
- mOverlayManager = null;
- int navBarModeKids = StatusBarManager.NAV_BAR_MODE_KIDS;
-
- mStatusBarManagerService.setNavBarMode(navBarModeKids);
-
- assertEquals(navBarModeKids, mStatusBarManagerService.getNavBarMode());
- verify(mOverlayManager, never()).setEnabledExclusiveInCategory(anyString(), anyInt());
- }
-
- @Test
public void testSetNavBarMode_noPackageDoesNotEnable() throws Exception {
mContext.setMockPackageManager(mPackageManager);
when(mPackageManager.getPackageInfo(anyString(),
diff --git a/services/tests/uiservicestests/src/com/android/server/notification/ZenModeHelperTest.java b/services/tests/uiservicestests/src/com/android/server/notification/ZenModeHelperTest.java
index 31be33e..fd1536c 100644
--- a/services/tests/uiservicestests/src/com/android/server/notification/ZenModeHelperTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/ZenModeHelperTest.java
@@ -43,6 +43,7 @@
import static com.android.os.AtomsProto.DNDModeProto.ID_FIELD_NUMBER;
import static com.android.os.AtomsProto.DNDModeProto.UID_FIELD_NUMBER;
import static com.android.os.AtomsProto.DNDModeProto.ZEN_MODE_FIELD_NUMBER;
+import static com.android.server.notification.ZenModeHelper.RULE_LIMIT_PER_PACKAGE;
import static junit.framework.Assert.assertEquals;
import static junit.framework.Assert.assertFalse;
@@ -1611,6 +1612,35 @@
}
@Test
+ public void testAddAutomaticZenRule_beyondSystemLimit() {
+ for (int i = 0; i < RULE_LIMIT_PER_PACKAGE; i++) {
+ ScheduleInfo si = new ScheduleInfo();
+ si.startHour = i;
+ AutomaticZenRule zenRule = new AutomaticZenRule("name" + i,
+ null,
+ new ComponentName("android", "ScheduleConditionProvider"),
+ ZenModeConfig.toScheduleConditionId(si),
+ new ZenPolicy.Builder().build(),
+ NotificationManager.INTERRUPTION_FILTER_PRIORITY, true);
+ String id = mZenModeHelperSpy.addAutomaticZenRule("android", zenRule, "test");
+ assertNotNull(id);
+ }
+ try {
+ AutomaticZenRule zenRule = new AutomaticZenRule("name",
+ null,
+ new ComponentName("android", "ScheduleConditionProvider"),
+ ZenModeConfig.toScheduleConditionId(new ScheduleInfo()),
+ new ZenPolicy.Builder().build(),
+ NotificationManager.INTERRUPTION_FILTER_PRIORITY, true);
+ String id = mZenModeHelperSpy.addAutomaticZenRule("android", zenRule, "test");
+ fail("allowed too many rules to be created");
+ } catch (IllegalArgumentException e) {
+ // yay
+ }
+
+ }
+
+ @Test
public void testAddAutomaticZenRule_CA() {
AutomaticZenRule zenRule = new AutomaticZenRule("name",
null,
diff --git a/services/tests/wmtests/src/com/android/server/wm/ActivityMetricsLaunchObserverTests.java b/services/tests/wmtests/src/com/android/server/wm/ActivityMetricsLaunchObserverTests.java
index d4d8b868..7689e08 100644
--- a/services/tests/wmtests/src/com/android/server/wm/ActivityMetricsLaunchObserverTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/ActivityMetricsLaunchObserverTests.java
@@ -256,6 +256,14 @@
mActivityMetricsLogger.notifyVisibilityChanged(noDrawnActivity);
verifyAsync(mLaunchObserver).onActivityLaunchCancelled(eqProto(noDrawnActivity));
+
+ // If an activity is removed immediately before visibility update, it should cancel too.
+ final ActivityRecord removedImm = new ActivityBuilder(mAtm).setCreateTask(true).build();
+ clearInvocations(mLaunchObserver);
+ onActivityLaunched(removedImm);
+ removedImm.removeImmediately();
+ // Verify any() instead of proto because the field of record may be changed.
+ verifyAsync(mLaunchObserver).onActivityLaunchCancelled(any());
}
@Test
@@ -299,15 +307,16 @@
@Test
public void testOnReportFullyDrawn() {
// Create an invisible event that should be cancelled after the next event starts.
- onActivityLaunched(mTrampolineActivity);
- mTrampolineActivity.mVisibleRequested = false;
+ final ActivityRecord prev = new ActivityBuilder(mAtm).setCreateTask(true).build();
+ onActivityLaunched(prev);
+ prev.mVisibleRequested = false;
mActivityOptions = ActivityOptions.makeBasic();
mActivityOptions.setSourceInfo(SourceInfo.TYPE_LAUNCHER, SystemClock.uptimeMillis() - 10);
onIntentStarted(mTopActivity.intent);
notifyActivityLaunched(START_SUCCESS, mTopActivity);
verifyAsync(mLaunchObserver).onActivityLaunched(eqProto(mTopActivity), anyInt());
- verifyAsync(mLaunchObserver).onActivityLaunchCancelled(eqProto(mTrampolineActivity));
+ verifyAsync(mLaunchObserver).onActivityLaunchCancelled(eqProto(prev));
// The activity reports fully drawn before windows drawn, then the fully drawn event will
// be pending (see {@link WindowingModeTransitionInfo#pendingFullyDrawn}).
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 f9aa4b1..9902e83 100644
--- a/services/tests/wmtests/src/com/android/server/wm/ActivityStarterTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/ActivityStarterTests.java
@@ -500,6 +500,23 @@
return Pair.create(splitPrimaryActivity, splitSecondActivity);
}
+ @Test
+ public void testMoveVisibleTaskToFront() {
+ final ActivityRecord activity = new TaskBuilder(mSupervisor)
+ .setCreateActivity(true).build().getTopMostActivity();
+ final ActivityRecord translucentActivity = new TaskBuilder(mSupervisor)
+ .setCreateActivity(true).build().getTopMostActivity();
+ assertTrue(activity.mVisibleRequested);
+
+ final ActivityStarter starter = prepareStarter(FLAG_ACTIVITY_NEW_TASK,
+ false /* mockGetRootTask */);
+ starter.getIntent().setComponent(activity.mActivityComponent);
+ final int result = starter.setReason("testMoveVisibleTaskToFront").execute();
+
+ assertEquals(START_TASK_TO_FRONT, result);
+ assertEquals(1, activity.compareTo(translucentActivity));
+ }
+
/**
* Tests activity is cleaned up properly in a task mode violation.
*/
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 c21a5b6..92550a3 100644
--- a/services/tests/wmtests/src/com/android/server/wm/BackNavigationControllerTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/BackNavigationControllerTests.java
@@ -30,7 +30,10 @@
import android.annotation.NonNull;
import android.hardware.HardwareBuffer;
import android.platform.test.annotations.Presubmit;
+import android.window.BackEvent;
import android.window.BackNavigationInfo;
+import android.window.IOnBackInvokedCallback;
+import android.window.OnBackInvokedDispatcher;
import android.window.TaskSnapshot;
import org.junit.Before;
@@ -42,15 +45,19 @@
public class BackNavigationControllerTests extends WindowTestsBase {
private BackNavigationController mBackNavigationController;
+ private IOnBackInvokedCallback mOnBackInvokedCallback;
@Before
public void setUp() throws Exception {
mBackNavigationController = new BackNavigationController();
+ mOnBackInvokedCallback = createBackCallback();
}
@Test
public void backTypeHomeWhenBackToLauncher() {
Task task = createTopTaskWithActivity();
+ registerSystemOnBackInvokedCallback();
+
BackNavigationInfo backNavigationInfo =
mBackNavigationController.startBackNavigation(task, new StubTransaction());
assertThat(backNavigationInfo).isNotNull();
@@ -63,6 +70,8 @@
Task taskA = createTask(mDefaultDisplay);
createActivityRecord(taskA);
Task task = createTopTaskWithActivity();
+ registerSystemOnBackInvokedCallback();
+
BackNavigationInfo backNavigationInfo =
mBackNavigationController.startBackNavigation(task, new StubTransaction());
assertThat(backNavigationInfo).isNotNull();
@@ -75,6 +84,8 @@
Task task = createTopTaskWithActivity();
mAtm.setFocusedTask(task.mTaskId,
createAppWindow(task, FIRST_APPLICATION_WINDOW, "window").mActivityRecord);
+ registerSystemOnBackInvokedCallback();
+
BackNavigationInfo backNavigationInfo =
mBackNavigationController.startBackNavigation(task, new StubTransaction());
assertThat(backNavigationInfo).isNotNull();
@@ -89,6 +100,7 @@
public void backNavInfoFullyPopulated() {
Task task = createTopTaskWithActivity();
createAppWindow(task, FIRST_APPLICATION_WINDOW, "window");
+ registerSystemOnBackInvokedCallback();
// We need a mock screenshot so
TaskSnapshotController taskSnapshotController = createMockTaskSnapshotController();
@@ -104,6 +116,30 @@
assertThat(backNavigationInfo.getTaskWindowConfiguration()).isNotNull();
}
+ @Test
+ public void preparesForBackToHome() {
+ Task task = createTopTaskWithActivity();
+ ActivityRecord activity = task.getTopActivity(false, false);
+ registerSystemOnBackInvokedCallback();
+
+ BackNavigationInfo backNavigationInfo =
+ mBackNavigationController.startBackNavigation(task, new StubTransaction());
+ assertThat(typeToString(backNavigationInfo.getType()))
+ .isEqualTo(typeToString(BackNavigationInfo.TYPE_RETURN_TO_HOME));
+ }
+
+ @Test
+ public void backTypeCallback() {
+ Task task = createTopTaskWithActivity();
+ ActivityRecord activity = task.getTopActivity(false, false);
+ registerApplicationOnBackInvokedCallback();
+
+ BackNavigationInfo backNavigationInfo =
+ mBackNavigationController.startBackNavigation(task, new StubTransaction());
+ assertThat(typeToString(backNavigationInfo.getType()))
+ .isEqualTo(typeToString(BackNavigationInfo.TYPE_CALLBACK));
+ }
+
@NonNull
private TaskSnapshotController createMockTaskSnapshotController() {
TaskSnapshotController taskSnapshotController = mock(TaskSnapshotController.class);
@@ -126,4 +162,30 @@
mAtm.setFocusedTask(task.mTaskId, record);
return task;
}
+
+ private void registerSystemOnBackInvokedCallback() {
+ mWm.getFocusedWindowLocked().setOnBackInvokedCallback(
+ mOnBackInvokedCallback, OnBackInvokedDispatcher.PRIORITY_SYSTEM);
+ }
+
+ private void registerApplicationOnBackInvokedCallback() {
+ mWm.getFocusedWindowLocked().setOnBackInvokedCallback(
+ mOnBackInvokedCallback, OnBackInvokedDispatcher.PRIORITY_DEFAULT);
+ }
+
+ private IOnBackInvokedCallback createBackCallback() {
+ return new IOnBackInvokedCallback.Stub() {
+ @Override
+ public void onBackStarted() { }
+
+ @Override
+ public void onBackProgressed(BackEvent backEvent) { }
+
+ @Override
+ public void onBackCancelled() { }
+
+ @Override
+ public void onBackInvoked() { }
+ };
+ }
}
diff --git a/services/tests/wmtests/src/com/android/server/wm/ContentRecorderTests.java b/services/tests/wmtests/src/com/android/server/wm/ContentRecorderTests.java
index 50eefa0..c5117bb 100644
--- a/services/tests/wmtests/src/com/android/server/wm/ContentRecorderTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/ContentRecorderTests.java
@@ -19,12 +19,12 @@
import static android.content.res.Configuration.ORIENTATION_PORTRAIT;
import static android.hardware.display.DisplayManager.VIRTUAL_DISPLAY_FLAG_AUTO_MIRROR;
-import static android.view.ContentRecordingSession.RECORD_CONTENT_TASK;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.any;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.spyOn;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.verify;
+import static com.android.server.wm.ContentRecorder.KEY_RECORD_TASK_FEATURE;
import static com.google.common.truth.Truth.assertThat;
@@ -40,17 +40,22 @@
import android.os.Binder;
import android.os.IBinder;
import android.platform.test.annotations.Presubmit;
+import android.provider.DeviceConfig;
import android.util.DisplayMetrics;
import android.view.ContentRecordingSession;
import android.view.Surface;
import android.view.SurfaceControl;
+import androidx.annotation.NonNull;
import androidx.test.filters.SmallTest;
+import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
+import java.util.concurrent.CountDownLatch;
+
/**
* Tests for the {@link ContentRecorder} class.
*
@@ -62,17 +67,18 @@
@RunWith(WindowTestRunner.class)
public class ContentRecorderTests extends WindowTestsBase {
private static final IBinder TEST_TOKEN = new RecordingTestToken();
- private final ContentRecordingSession mDefaultSession =
+ private static IBinder sTaskWindowContainerToken;
+ private final ContentRecordingSession mDisplaySession =
ContentRecordingSession.createDisplaySession(TEST_TOKEN);
+ private ContentRecordingSession mTaskSession;
private static Point sSurfaceSize;
private ContentRecorder mContentRecorder;
private SurfaceControl mRecordedSurface;
+ // Handle feature flag.
+ private ConfigListener mConfigListener;
+ private CountDownLatch mLatch;
@Before public void setUp() {
- // GIVEN MediaProjection has already initialized the WindowToken of the DisplayArea to
- // mirror.
- setUpDefaultTaskDisplayAreaWindowToken();
-
// GIVEN SurfaceControl can successfully mirror the provided surface.
sSurfaceSize = new Point(
mDefaultDisplay.getDefaultTaskDisplayArea().getBounds().width(),
@@ -84,12 +90,32 @@
sSurfaceSize.x, sSurfaceSize.y,
DisplayMetrics.DENSITY_140, new Surface(), VIRTUAL_DISPLAY_FLAG_AUTO_MIRROR);
final int displayId = virtualDisplay.getDisplay().getDisplayId();
- mDefaultSession.setDisplayId(displayId);
-
mWm.mRoot.onDisplayAdded(displayId);
- final DisplayContent mVirtualDisplayContent = mWm.mRoot.getDisplayContent(displayId);
- mContentRecorder = new ContentRecorder(mVirtualDisplayContent);
- spyOn(mVirtualDisplayContent);
+ final DisplayContent virtualDisplayContent = mWm.mRoot.getDisplayContent(displayId);
+ mContentRecorder = new ContentRecorder(virtualDisplayContent);
+ spyOn(virtualDisplayContent);
+
+ // GIVEN MediaProjection has already initialized the WindowToken of the DisplayArea to
+ // record.
+ setUpDefaultTaskDisplayAreaWindowToken();
+ mDisplaySession.setDisplayId(displayId);
+
+ // GIVEN there is a window token associated with a task to record.
+ sTaskWindowContainerToken = setUpTaskWindowContainerToken(virtualDisplayContent);
+ mTaskSession = ContentRecordingSession.createTaskSession(sTaskWindowContainerToken);
+ mTaskSession.setDisplayId(displayId);
+
+ mConfigListener = new ConfigListener();
+ DeviceConfig.addOnPropertiesChangedListener(DeviceConfig.NAMESPACE_WINDOW_MANAGER,
+ mContext.getMainExecutor(), mConfigListener);
+ mLatch = new CountDownLatch(1);
+ DeviceConfig.setProperty(DeviceConfig.NAMESPACE_WINDOW_MANAGER, KEY_RECORD_TASK_FEATURE,
+ "true", true);
+ }
+
+ @After
+ public void teardown() {
+ DeviceConfig.removeOnPropertiesChangedListener(mConfigListener);
}
@Test
@@ -102,22 +128,74 @@
@Test
public void testUpdateRecording_display() {
- mContentRecorder.setContentRecordingSession(mDefaultSession);
+ mContentRecorder.setContentRecordingSession(mDisplaySession);
mContentRecorder.updateRecording();
assertThat(mContentRecorder.isCurrentlyRecording()).isTrue();
}
@Test
- public void testUpdateRecording_task() {
- mDefaultSession.setContentToRecord(RECORD_CONTENT_TASK);
- mContentRecorder.setContentRecordingSession(mDefaultSession);
+ public void testUpdateRecording_display_nullToken() {
+ ContentRecordingSession session = ContentRecordingSession.createDisplaySession(TEST_TOKEN);
+ session.setDisplayId(mDisplaySession.getDisplayId());
+ session.setTokenToRecord(null);
+ mContentRecorder.setContentRecordingSession(session);
mContentRecorder.updateRecording();
assertThat(mContentRecorder.isCurrentlyRecording()).isFalse();
}
@Test
+ public void testUpdateRecording_display_noWindowContainer() {
+ doReturn(null).when(
+ mWm.mWindowContextListenerController).getContainer(any());
+ mContentRecorder.setContentRecordingSession(mDisplaySession);
+ mContentRecorder.updateRecording();
+ assertThat(mContentRecorder.isCurrentlyRecording()).isFalse();
+ }
+
+ @Test
+ public void testUpdateRecording_task_featureDisabled() {
+ mLatch = new CountDownLatch(1);
+ DeviceConfig.setProperty(DeviceConfig.NAMESPACE_WINDOW_MANAGER, KEY_RECORD_TASK_FEATURE,
+ "false", false);
+ mContentRecorder.setContentRecordingSession(mTaskSession);
+ mContentRecorder.updateRecording();
+ assertThat(mContentRecorder.isCurrentlyRecording()).isFalse();
+ }
+
+ @Test
+ public void testUpdateRecording_task_featureEnabled() {
+ // Feature already enabled; don't need to again.
+ mContentRecorder.setContentRecordingSession(mTaskSession);
+ mContentRecorder.updateRecording();
+ assertThat(mContentRecorder.isCurrentlyRecording()).isTrue();
+ }
+
+ @Test
+ public void testUpdateRecording_task_nullToken() {
+ ContentRecordingSession session = ContentRecordingSession.createTaskSession(
+ sTaskWindowContainerToken);
+ session.setDisplayId(mDisplaySession.getDisplayId());
+ session.setTokenToRecord(null);
+ mContentRecorder.setContentRecordingSession(session);
+ mContentRecorder.updateRecording();
+ assertThat(mContentRecorder.isCurrentlyRecording()).isFalse();
+ // TODO(b/219761722) validate VirtualDisplay is torn down when can't set up task recording.
+ }
+
+ @Test
+ public void testUpdateRecording_task_noWindowContainer() {
+ // Use the window container token of the DisplayContent, rather than task.
+ ContentRecordingSession invalidTaskSession = ContentRecordingSession.createTaskSession(
+ new WindowContainer.RemoteToken(mDisplayContent));
+ mContentRecorder.setContentRecordingSession(invalidTaskSession);
+ mContentRecorder.updateRecording();
+ assertThat(mContentRecorder.isCurrentlyRecording()).isFalse();
+ // TODO(b/219761722) validate VirtualDisplay is torn down when can't set up task recording.
+ }
+
+ @Test
public void testUpdateRecording_wasPaused() {
- mContentRecorder.setContentRecordingSession(mDefaultSession);
+ mContentRecorder.setContentRecordingSession(mDisplaySession);
mContentRecorder.updateRecording();
mContentRecorder.pauseRecording();
@@ -126,16 +204,6 @@
}
@Test
- public void testUpdateRecording_wasStopped() {
- mContentRecorder.setContentRecordingSession(mDefaultSession);
- mContentRecorder.updateRecording();
-
- mContentRecorder.remove();
- mContentRecorder.updateRecording();
- assertThat(mContentRecorder.isCurrentlyRecording()).isFalse();
- }
-
- @Test
public void testOnConfigurationChanged_neverRecording() {
mContentRecorder.onConfigurationChanged(ORIENTATION_PORTRAIT);
@@ -146,7 +214,7 @@
@Test
public void testOnConfigurationChanged_resizesSurface() {
- mContentRecorder.setContentRecordingSession(mDefaultSession);
+ mContentRecorder.setContentRecordingSession(mDisplaySession);
mContentRecorder.updateRecording();
mContentRecorder.onConfigurationChanged(ORIENTATION_PORTRAIT);
@@ -158,7 +226,7 @@
@Test
public void testPauseRecording_pausesRecording() {
- mContentRecorder.setContentRecordingSession(mDefaultSession);
+ mContentRecorder.setContentRecordingSession(mDisplaySession);
mContentRecorder.updateRecording();
mContentRecorder.pauseRecording();
@@ -173,7 +241,7 @@
@Test
public void testRemove_stopsRecording() {
- mContentRecorder.setContentRecordingSession(mDefaultSession);
+ mContentRecorder.setContentRecordingSession(mDisplaySession);
mContentRecorder.updateRecording();
mContentRecorder.remove();
@@ -188,8 +256,9 @@
@Test
public void testUpdateMirroredSurface_capturedAreaResized() {
- mContentRecorder.setContentRecordingSession(mDefaultSession);
+ mContentRecorder.setContentRecordingSession(mDisplaySession);
mContentRecorder.updateRecording();
+ assertThat(mContentRecorder.isCurrentlyRecording()).isTrue();
// WHEN attempting to mirror on the virtual display, and the captured content is resized.
float xScale = 0.7f;
@@ -197,13 +266,14 @@
Rect displayAreaBounds = new Rect(0, 0, Math.round(sSurfaceSize.x * xScale),
Math.round(sSurfaceSize.y * yScale));
mContentRecorder.updateMirroredSurface(mTransaction, displayAreaBounds, sSurfaceSize);
+ assertThat(mContentRecorder.isCurrentlyRecording()).isTrue();
// THEN content in the captured DisplayArea is scaled to fit the surface size.
verify(mTransaction, atLeastOnce()).setMatrix(mRecordedSurface, 1.0f / yScale, 0, 0,
1.0f / yScale);
// THEN captured content is positioned in the centre of the output surface.
- float scaledWidth = displayAreaBounds.width() / xScale;
- float xInset = (sSurfaceSize.x - scaledWidth) / 2;
+ int scaledWidth = Math.round((float) displayAreaBounds.width() / xScale);
+ int xInset = (sSurfaceSize.x - scaledWidth) / 2;
verify(mTransaction, atLeastOnce()).setPosition(mRecordedSurface, xInset, 0);
}
@@ -222,6 +292,18 @@
}
/**
+ * Creates a {@link android.window.WindowContainerToken} associated with a task, in order for
+ * that task to be recorded.
+ */
+ private IBinder setUpTaskWindowContainerToken(DisplayContent displayContent) {
+ final Task rootTask = createTask(displayContent);
+ final Task task = createTaskInRootTask(rootTask, 0 /* userId */);
+ // Ensure the task is not empty.
+ createActivityRecord(displayContent, task);
+ return task.getTaskInfo().token.asBinder();
+ }
+
+ /**
* SurfaceControl successfully creates a mirrored surface of the given size.
*/
private SurfaceControl surfaceControlMirrors(Point surfaceSize) {
@@ -236,4 +318,13 @@
anyInt());
return mirroredSurface;
}
+
+ private class ConfigListener implements DeviceConfig.OnPropertiesChangedListener {
+ @Override
+ public void onPropertiesChanged(@NonNull DeviceConfig.Properties properties) {
+ if (mLatch != null && properties.getKeyset().contains(KEY_RECORD_TASK_FEATURE)) {
+ mLatch.countDown();
+ }
+ }
+ }
}
diff --git a/services/tests/wmtests/src/com/android/server/wm/DisplayPolicyLayoutTests.java b/services/tests/wmtests/src/com/android/server/wm/DisplayPolicyLayoutTests.java
index db22757..45ae81a 100644
--- a/services/tests/wmtests/src/com/android/server/wm/DisplayPolicyLayoutTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/DisplayPolicyLayoutTests.java
@@ -157,6 +157,7 @@
win.getFrame().set(0, 0, 500, 100);
addWindow(win);
+ win.updateSourceFrame(win.getFrame());
InsetsStateController controller = mDisplayContent.getInsetsStateController();
controller.onPostLayout();
@@ -185,6 +186,7 @@
win.getFrame().set(0, 0, 500, 100);
addWindow(win);
+ win.updateSourceFrame(win.getFrame());
mDisplayContent.getInsetsStateController().onPostLayout();
InsetsSourceProvider provider =
diff --git a/services/tests/wmtests/src/com/android/server/wm/InsetsStateControllerTest.java b/services/tests/wmtests/src/com/android/server/wm/InsetsStateControllerTest.java
index 90a6918..6d02226 100644
--- a/services/tests/wmtests/src/com/android/server/wm/InsetsStateControllerTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/InsetsStateControllerTest.java
@@ -280,6 +280,7 @@
rect.set(0, 1, 2, 3)));
getController().getSourceProvider(ITYPE_IME).setWindowContainer(ime, null, null);
statusBar.setControllableInsetProvider(statusBarProvider);
+ statusBar.updateSourceFrame(statusBar.getFrame());
statusBarProvider.onPostLayout();
diff --git a/services/tests/wmtests/src/com/android/server/wm/TaskTests.java b/services/tests/wmtests/src/com/android/server/wm/TaskTests.java
index 636c6bc..9304761 100644
--- a/services/tests/wmtests/src/com/android/server/wm/TaskTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/TaskTests.java
@@ -259,6 +259,20 @@
}
@Test
+ public void testPerformClearTop() {
+ final Task task = createTask(mDisplayContent);
+ final ActivityRecord activity1 = new ActivityBuilder(mAtm).setTask(task).build();
+ final ActivityRecord activity2 = new ActivityBuilder(mAtm).setTask(task).build();
+ // Detach from process so the activities can be removed from hierarchy when finishing.
+ activity1.detachFromProcess();
+ activity2.detachFromProcess();
+ assertNull(task.performClearTop(activity1, 0 /* launchFlags */));
+ assertFalse(task.hasChild());
+ // In real case, the task should be preserved for adding new activity.
+ assertTrue(task.isAttached());
+ }
+
+ @Test
public void testRemoveChildForOverlayTask() {
final Task task = createTask(mDisplayContent);
final int taskId = task.mTaskId;
diff --git a/services/tests/wmtests/src/com/android/server/wm/TestIWindow.java b/services/tests/wmtests/src/com/android/server/wm/TestIWindow.java
index 7dfb5ae..4f35d55 100644
--- a/services/tests/wmtests/src/com/android/server/wm/TestIWindow.java
+++ b/services/tests/wmtests/src/com/android/server/wm/TestIWindow.java
@@ -44,7 +44,7 @@
@Override
public void resized(ClientWindowFrames frames, boolean reportDraw,
MergedConfiguration mergedConfig, boolean forceLayout, boolean alwaysConsumeSystemBars,
- int displayId) throws RemoteException {
+ int displayId, int seqId) throws RemoteException {
}
@Override
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 c4547f6..7e5d017 100644
--- a/services/tests/wmtests/src/com/android/server/wm/TransitionTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/TransitionTests.java
@@ -692,7 +692,8 @@
statusBar.mWinAnimator.mDrawState = WindowStateAnimator.DRAW_PENDING;
final SurfaceControl.Transaction postDrawTransaction =
mock(SurfaceControl.Transaction.class);
- final boolean layoutNeeded = statusBar.finishDrawing(postDrawTransaction);
+ final boolean layoutNeeded = statusBar.finishDrawing(postDrawTransaction,
+ Integer.MAX_VALUE);
assertFalse(layoutNeeded);
transactionCommittedListener.onTransactionCommitted();
@@ -742,7 +743,7 @@
player.finish();
// The controller should be cleared if the target windows are drawn.
- statusBar.finishDrawing(mWm.mTransactionFactory.get());
+ statusBar.finishDrawing(mWm.mTransactionFactory.get(), Integer.MAX_VALUE);
statusBar.setOrientationChanging(false);
assertNull(mDisplayContent.getAsyncRotationController());
}
diff --git a/services/tests/wmtests/src/com/android/server/wm/WindowContainerInsetsSourceProviderTest.java b/services/tests/wmtests/src/com/android/server/wm/WindowContainerInsetsSourceProviderTest.java
index 10e4292..e824f3d 100644
--- a/services/tests/wmtests/src/com/android/server/wm/WindowContainerInsetsSourceProviderTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/WindowContainerInsetsSourceProviderTest.java
@@ -64,6 +64,7 @@
statusBar.getFrame().set(0, 0, 500, 100);
statusBar.mHasSurface = true;
mProvider.setWindowContainer(statusBar, null, null);
+ mProvider.updateSourceFrame(statusBar.getFrame());
mProvider.onPostLayout();
assertEquals(new Rect(0, 0, 500, 100), mProvider.getSource().getFrame());
assertEquals(Insets.of(0, 100, 0, 0),
@@ -81,6 +82,7 @@
ime.mGivenVisibleInsets.set(0, 0, 0, 75);
ime.mHasSurface = true;
mProvider.setWindowContainer(ime, null, null);
+ mProvider.updateSourceFrame(ime.getFrame());
mProvider.onPostLayout();
assertEquals(new Rect(0, 0, 500, 40), mProvider.getSource().getFrame());
assertEquals(new Rect(0, 0, 500, 25), mProvider.getSource().getVisibleFrame());
@@ -96,6 +98,7 @@
final WindowState statusBar = createWindow(null, TYPE_APPLICATION, "statusBar");
statusBar.getFrame().set(0, 0, 500, 100);
mProvider.setWindowContainer(statusBar, null, null);
+ mProvider.updateSourceFrame(statusBar.getFrame());
mProvider.onPostLayout();
assertEquals(Insets.NONE, mProvider.getSource().calculateInsets(new Rect(0, 0, 500, 500),
false /* ignoreVisibility */));
@@ -110,6 +113,7 @@
(displayFrames, windowState, rect) -> {
rect.set(10, 10, 20, 20);
}, null);
+ mProvider.updateSourceFrame(statusBar.getFrame());
mProvider.onPostLayout();
assertEquals(new Rect(10, 10, 20, 20), mProvider.getSource().getFrame());
}
@@ -181,7 +185,7 @@
mImeProvider.setWindowContainer(inputMethod, null, null);
mImeProvider.setServerVisible(false);
mImeSource.setVisible(true);
- mImeProvider.updateSourceFrame();
+ mImeProvider.updateSourceFrame(inputMethod.getFrame());
assertEquals(new Rect(0, 0, 0, 0), mImeSource.getFrame());
Insets insets = mImeSource.calculateInsets(new Rect(0, 0, 500, 500),
false /* ignoreVisibility */);
@@ -189,7 +193,7 @@
mImeProvider.setServerVisible(true);
mImeSource.setVisible(true);
- mImeProvider.updateSourceFrame();
+ mImeProvider.updateSourceFrame(inputMethod.getFrame());
assertEquals(inputMethod.getFrame(), mImeSource.getFrame());
insets = mImeSource.calculateInsets(new Rect(0, 0, 500, 500),
false /* ignoreVisibility */);
@@ -229,6 +233,7 @@
statusBar.getFrame().set(0, 0, 500, 100);
statusBar.mHasSurface = true;
mProvider.setWindowContainer(statusBar, null, null);
+ mProvider.updateSourceFrame(statusBar.getFrame());
mProvider.onPostLayout();
assertEquals(new Rect(0, 0, 500, 100), mProvider.getSource().getFrame());
// Still apply top insets if window overlaps even if it's top doesn't exactly match
diff --git a/services/tests/wmtests/src/com/android/server/wm/WindowLayoutTests.java b/services/tests/wmtests/src/com/android/server/wm/WindowLayoutTests.java
index 7d2e9bf..ea18e58 100644
--- a/services/tests/wmtests/src/com/android/server/wm/WindowLayoutTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/WindowLayoutTests.java
@@ -45,6 +45,7 @@
import android.view.WindowInsets;
import android.view.WindowLayout;
import android.view.WindowManager;
+import android.window.ClientWindowFrames;
import androidx.test.filters.SmallTest;
@@ -71,9 +72,7 @@
private static final Insets WATERFALL_INSETS = Insets.of(6, 0, 12, 0);
private final WindowLayout mWindowLayout = new WindowLayout();
- private final Rect mDisplayFrame = new Rect();
- private final Rect mParentFrame = new Rect();
- private final Rect mFrame = new Rect();
+ private final ClientWindowFrames mOutFrames = new ClientWindowFrames();
private WindowManager.LayoutParams mAttrs;
private InsetsState mState;
@@ -108,7 +107,7 @@
private void computeFrames() {
mWindowLayout.computeFrames(mAttrs, mState, mDisplayCutoutSafe, mWindowBounds,
mWindowingMode, mRequestedWidth, mRequestedHeight, mRequestedVisibilities,
- mAttachedWindowFrame, mCompatScale, mDisplayFrame, mParentFrame, mFrame);
+ mAttachedWindowFrame, mCompatScale, mOutFrames);
}
private void addDisplayCutout() {
@@ -146,9 +145,9 @@
public void defaultParams() {
computeFrames();
- assertInsetByTopBottom(STATUS_BAR_HEIGHT, NAVIGATION_BAR_HEIGHT, mDisplayFrame);
- assertInsetByTopBottom(STATUS_BAR_HEIGHT, NAVIGATION_BAR_HEIGHT, mParentFrame);
- assertInsetByTopBottom(STATUS_BAR_HEIGHT, NAVIGATION_BAR_HEIGHT, mFrame);
+ assertInsetByTopBottom(STATUS_BAR_HEIGHT, NAVIGATION_BAR_HEIGHT, mOutFrames.displayFrame);
+ assertInsetByTopBottom(STATUS_BAR_HEIGHT, NAVIGATION_BAR_HEIGHT, mOutFrames.parentFrame);
+ assertInsetByTopBottom(STATUS_BAR_HEIGHT, NAVIGATION_BAR_HEIGHT, mOutFrames.frame);
}
@Test
@@ -157,9 +156,9 @@
mRequestedHeight = UNSPECIFIED_LENGTH;
computeFrames();
- assertInsetByTopBottom(STATUS_BAR_HEIGHT, NAVIGATION_BAR_HEIGHT, mDisplayFrame);
- assertInsetByTopBottom(STATUS_BAR_HEIGHT, NAVIGATION_BAR_HEIGHT, mParentFrame);
- assertInsetByTopBottom(STATUS_BAR_HEIGHT, NAVIGATION_BAR_HEIGHT, mFrame);
+ assertInsetByTopBottom(STATUS_BAR_HEIGHT, NAVIGATION_BAR_HEIGHT, mOutFrames.displayFrame);
+ assertInsetByTopBottom(STATUS_BAR_HEIGHT, NAVIGATION_BAR_HEIGHT, mOutFrames.parentFrame);
+ assertInsetByTopBottom(STATUS_BAR_HEIGHT, NAVIGATION_BAR_HEIGHT, mOutFrames.frame);
}
@Test
@@ -173,9 +172,9 @@
mAttrs.gravity = Gravity.LEFT | Gravity.TOP;
computeFrames();
- assertInsetByTopBottom(STATUS_BAR_HEIGHT, NAVIGATION_BAR_HEIGHT, mDisplayFrame);
- assertInsetByTopBottom(STATUS_BAR_HEIGHT, NAVIGATION_BAR_HEIGHT, mParentFrame);
- assertRect(0, STATUS_BAR_HEIGHT, width, STATUS_BAR_HEIGHT + height, mFrame);
+ assertInsetByTopBottom(STATUS_BAR_HEIGHT, NAVIGATION_BAR_HEIGHT, mOutFrames.displayFrame);
+ assertInsetByTopBottom(STATUS_BAR_HEIGHT, NAVIGATION_BAR_HEIGHT, mOutFrames.parentFrame);
+ assertRect(0, STATUS_BAR_HEIGHT, width, STATUS_BAR_HEIGHT + height, mOutFrames.frame);
}
@Test
@@ -186,9 +185,12 @@
mRequestedHeight = UNSPECIFIED_LENGTH;
computeFrames();
- assertRect(0, top, DISPLAY_WIDTH, DISPLAY_HEIGHT - NAVIGATION_BAR_HEIGHT, mDisplayFrame);
- assertRect(0, top, DISPLAY_WIDTH, DISPLAY_HEIGHT - NAVIGATION_BAR_HEIGHT, mParentFrame);
- assertRect(0, top, DISPLAY_WIDTH, DISPLAY_HEIGHT - NAVIGATION_BAR_HEIGHT, mFrame);
+ assertRect(0, top, DISPLAY_WIDTH, DISPLAY_HEIGHT - NAVIGATION_BAR_HEIGHT,
+ mOutFrames.displayFrame);
+ assertRect(0, top, DISPLAY_WIDTH, DISPLAY_HEIGHT - NAVIGATION_BAR_HEIGHT,
+ mOutFrames.parentFrame);
+ assertRect(0, top, DISPLAY_WIDTH, DISPLAY_HEIGHT - NAVIGATION_BAR_HEIGHT,
+ mOutFrames.frame);
}
@Test
@@ -196,9 +198,9 @@
mAttrs.setFitInsetsTypes(WindowInsets.Type.statusBars());
computeFrames();
- assertInsetByTopBottom(STATUS_BAR_HEIGHT, 0, mDisplayFrame);
- assertInsetByTopBottom(STATUS_BAR_HEIGHT, 0, mParentFrame);
- assertInsetByTopBottom(STATUS_BAR_HEIGHT, 0, mFrame);
+ assertInsetByTopBottom(STATUS_BAR_HEIGHT, 0, mOutFrames.displayFrame);
+ assertInsetByTopBottom(STATUS_BAR_HEIGHT, 0, mOutFrames.parentFrame);
+ assertInsetByTopBottom(STATUS_BAR_HEIGHT, 0, mOutFrames.frame);
}
@Test
@@ -206,9 +208,9 @@
mAttrs.setFitInsetsTypes(WindowInsets.Type.navigationBars());
computeFrames();
- assertInsetByTopBottom(0, NAVIGATION_BAR_HEIGHT, mDisplayFrame);
- assertInsetByTopBottom(0, NAVIGATION_BAR_HEIGHT, mParentFrame);
- assertInsetByTopBottom(0, NAVIGATION_BAR_HEIGHT, mFrame);
+ assertInsetByTopBottom(0, NAVIGATION_BAR_HEIGHT, mOutFrames.displayFrame);
+ assertInsetByTopBottom(0, NAVIGATION_BAR_HEIGHT, mOutFrames.parentFrame);
+ assertInsetByTopBottom(0, NAVIGATION_BAR_HEIGHT, mOutFrames.frame);
}
@Test
@@ -216,9 +218,9 @@
mAttrs.setFitInsetsTypes(0);
computeFrames();
- assertInsetByTopBottom(0, 0, mDisplayFrame);
- assertInsetByTopBottom(0, 0, mParentFrame);
- assertInsetByTopBottom(0, 0, mFrame);
+ assertInsetByTopBottom(0, 0, mOutFrames.displayFrame);
+ assertInsetByTopBottom(0, 0, mOutFrames.parentFrame);
+ assertInsetByTopBottom(0, 0, mOutFrames.frame);
}
@Test
@@ -226,9 +228,9 @@
mAttrs.setFitInsetsSides(WindowInsets.Side.all());
computeFrames();
- assertInsetByTopBottom(STATUS_BAR_HEIGHT, NAVIGATION_BAR_HEIGHT, mDisplayFrame);
- assertInsetByTopBottom(STATUS_BAR_HEIGHT, NAVIGATION_BAR_HEIGHT, mParentFrame);
- assertInsetByTopBottom(STATUS_BAR_HEIGHT, NAVIGATION_BAR_HEIGHT, mFrame);
+ assertInsetByTopBottom(STATUS_BAR_HEIGHT, NAVIGATION_BAR_HEIGHT, mOutFrames.displayFrame);
+ assertInsetByTopBottom(STATUS_BAR_HEIGHT, NAVIGATION_BAR_HEIGHT, mOutFrames.parentFrame);
+ assertInsetByTopBottom(STATUS_BAR_HEIGHT, NAVIGATION_BAR_HEIGHT, mOutFrames.frame);
}
@Test
@@ -236,9 +238,9 @@
mAttrs.setFitInsetsSides(WindowInsets.Side.TOP);
computeFrames();
- assertInsetByTopBottom(STATUS_BAR_HEIGHT, 0, mDisplayFrame);
- assertInsetByTopBottom(STATUS_BAR_HEIGHT, 0, mParentFrame);
- assertInsetByTopBottom(STATUS_BAR_HEIGHT, 0, mFrame);
+ assertInsetByTopBottom(STATUS_BAR_HEIGHT, 0, mOutFrames.displayFrame);
+ assertInsetByTopBottom(STATUS_BAR_HEIGHT, 0, mOutFrames.parentFrame);
+ assertInsetByTopBottom(STATUS_BAR_HEIGHT, 0, mOutFrames.frame);
}
@Test
@@ -246,9 +248,9 @@
mAttrs.setFitInsetsSides(0);
computeFrames();
- assertInsetByTopBottom(0, 0, mDisplayFrame);
- assertInsetByTopBottom(0, 0, mParentFrame);
- assertInsetByTopBottom(0, 0, mFrame);
+ assertInsetByTopBottom(0, 0, mOutFrames.displayFrame);
+ assertInsetByTopBottom(0, 0, mOutFrames.parentFrame);
+ assertInsetByTopBottom(0, 0, mOutFrames.frame);
}
@Test
@@ -257,9 +259,9 @@
mState.getSource(ITYPE_NAVIGATION_BAR).setVisible(false);
computeFrames();
- assertInsetByTopBottom(0, 0, mDisplayFrame);
- assertInsetByTopBottom(0, 0, mParentFrame);
- assertInsetByTopBottom(0, 0, mFrame);
+ assertInsetByTopBottom(0, 0, mOutFrames.displayFrame);
+ assertInsetByTopBottom(0, 0, mOutFrames.parentFrame);
+ assertInsetByTopBottom(0, 0, mOutFrames.frame);
}
@Test
@@ -269,9 +271,9 @@
mAttrs.setFitInsetsIgnoringVisibility(true);
computeFrames();
- assertInsetByTopBottom(STATUS_BAR_HEIGHT, NAVIGATION_BAR_HEIGHT, mDisplayFrame);
- assertInsetByTopBottom(STATUS_BAR_HEIGHT, NAVIGATION_BAR_HEIGHT, mParentFrame);
- assertInsetByTopBottom(STATUS_BAR_HEIGHT, NAVIGATION_BAR_HEIGHT, mFrame);
+ assertInsetByTopBottom(STATUS_BAR_HEIGHT, NAVIGATION_BAR_HEIGHT, mOutFrames.displayFrame);
+ assertInsetByTopBottom(STATUS_BAR_HEIGHT, NAVIGATION_BAR_HEIGHT, mOutFrames.parentFrame);
+ assertInsetByTopBottom(STATUS_BAR_HEIGHT, NAVIGATION_BAR_HEIGHT, mOutFrames.frame);
}
@Test
@@ -282,9 +284,9 @@
mAttrs.privateFlags |= PRIVATE_FLAG_INSET_PARENT_FRAME_BY_IME;
computeFrames();
- assertInsetByTopBottom(STATUS_BAR_HEIGHT, NAVIGATION_BAR_HEIGHT, mDisplayFrame);
- assertInsetByTopBottom(STATUS_BAR_HEIGHT, IME_HEIGHT, mParentFrame);
- assertInsetByTopBottom(STATUS_BAR_HEIGHT, IME_HEIGHT, mFrame);
+ assertInsetByTopBottom(STATUS_BAR_HEIGHT, NAVIGATION_BAR_HEIGHT, mOutFrames.displayFrame);
+ assertInsetByTopBottom(STATUS_BAR_HEIGHT, IME_HEIGHT, mOutFrames.parentFrame);
+ assertInsetByTopBottom(STATUS_BAR_HEIGHT, IME_HEIGHT, mOutFrames.frame);
}
@Test
@@ -295,11 +297,11 @@
computeFrames();
assertInsetBy(WATERFALL_INSETS.left, DISPLAY_CUTOUT_HEIGHT, WATERFALL_INSETS.right, 0,
- mDisplayFrame);
+ mOutFrames.displayFrame);
assertInsetBy(WATERFALL_INSETS.left, DISPLAY_CUTOUT_HEIGHT, WATERFALL_INSETS.right, 0,
- mParentFrame);
+ mOutFrames.parentFrame);
assertInsetBy(WATERFALL_INSETS.left, DISPLAY_CUTOUT_HEIGHT, WATERFALL_INSETS.right, 0,
- mFrame);
+ mOutFrames.frame);
}
@Test
@@ -310,11 +312,11 @@
computeFrames();
assertInsetBy(WATERFALL_INSETS.left, STATUS_BAR_HEIGHT, WATERFALL_INSETS.right, 0,
- mDisplayFrame);
+ mOutFrames.displayFrame);
assertInsetBy(WATERFALL_INSETS.left, STATUS_BAR_HEIGHT, WATERFALL_INSETS.right, 0,
- mParentFrame);
+ mOutFrames.parentFrame);
assertInsetBy(WATERFALL_INSETS.left, STATUS_BAR_HEIGHT, WATERFALL_INSETS.right, 0,
- mFrame);
+ mOutFrames.frame);
}
@Test
@@ -325,9 +327,9 @@
mAttrs.setFitInsetsTypes(0);
computeFrames();
- assertInsetBy(WATERFALL_INSETS.left, 0, WATERFALL_INSETS.right, 0, mDisplayFrame);
- assertInsetBy(WATERFALL_INSETS.left, 0, WATERFALL_INSETS.right, 0, mParentFrame);
- assertInsetBy(WATERFALL_INSETS.left, 0, WATERFALL_INSETS.right, 0, mFrame);
+ assertInsetBy(WATERFALL_INSETS.left, 0, WATERFALL_INSETS.right, 0, mOutFrames.displayFrame);
+ assertInsetBy(WATERFALL_INSETS.left, 0, WATERFALL_INSETS.right, 0, mOutFrames.parentFrame);
+ assertInsetBy(WATERFALL_INSETS.left, 0, WATERFALL_INSETS.right, 0, mOutFrames.frame);
}
@Test
@@ -342,9 +344,9 @@
mAttrs.privateFlags |= PRIVATE_FLAG_LAYOUT_SIZE_EXTENDED_BY_CUTOUT;
computeFrames();
- assertRect(0, 0, DISPLAY_WIDTH, DISPLAY_HEIGHT, mDisplayFrame);
- assertRect(0, 0, DISPLAY_WIDTH, DISPLAY_HEIGHT, mParentFrame);
- assertRect(0, 0, DISPLAY_WIDTH, height + DISPLAY_CUTOUT_HEIGHT, mFrame);
+ assertRect(0, 0, DISPLAY_WIDTH, DISPLAY_HEIGHT, mOutFrames.displayFrame);
+ assertRect(0, 0, DISPLAY_WIDTH, DISPLAY_HEIGHT, mOutFrames.parentFrame);
+ assertRect(0, 0, DISPLAY_WIDTH, height + DISPLAY_CUTOUT_HEIGHT, mOutFrames.frame);
}
@Test
@@ -357,11 +359,11 @@
computeFrames();
assertInsetBy(WATERFALL_INSETS.left, STATUS_BAR_HEIGHT, WATERFALL_INSETS.right, 0,
- mDisplayFrame);
+ mOutFrames.displayFrame);
assertInsetBy(WATERFALL_INSETS.left, STATUS_BAR_HEIGHT, WATERFALL_INSETS.right, 0,
- mParentFrame);
+ mOutFrames.parentFrame);
assertInsetBy(WATERFALL_INSETS.left, STATUS_BAR_HEIGHT, WATERFALL_INSETS.right, 0,
- mFrame);
+ mOutFrames.frame);
}
@Test
@@ -371,9 +373,9 @@
mAttrs.setFitInsetsTypes(0);
computeFrames();
- assertInsetBy(WATERFALL_INSETS.left, 0, WATERFALL_INSETS.right, 0, mDisplayFrame);
- assertInsetBy(WATERFALL_INSETS.left, 0, WATERFALL_INSETS.right, 0, mParentFrame);
- assertInsetBy(WATERFALL_INSETS.left, 0, WATERFALL_INSETS.right, 0, mFrame);
+ assertInsetBy(WATERFALL_INSETS.left, 0, WATERFALL_INSETS.right, 0, mOutFrames.displayFrame);
+ assertInsetBy(WATERFALL_INSETS.left, 0, WATERFALL_INSETS.right, 0, mOutFrames.parentFrame);
+ assertInsetBy(WATERFALL_INSETS.left, 0, WATERFALL_INSETS.right, 0, mOutFrames.frame);
}
@Test
@@ -384,11 +386,11 @@
computeFrames();
assertInsetBy(WATERFALL_INSETS.left, STATUS_BAR_HEIGHT, WATERFALL_INSETS.right, 0,
- mDisplayFrame);
+ mOutFrames.displayFrame);
assertInsetBy(WATERFALL_INSETS.left, STATUS_BAR_HEIGHT, WATERFALL_INSETS.right, 0,
- mParentFrame);
+ mOutFrames.parentFrame);
assertInsetBy(WATERFALL_INSETS.left, STATUS_BAR_HEIGHT, WATERFALL_INSETS.right, 0,
- mFrame);
+ mOutFrames.frame);
}
@Test
@@ -398,8 +400,8 @@
mAttrs.setFitInsetsTypes(0);
computeFrames();
- assertInsetByTopBottom(0, 0, mDisplayFrame);
- assertInsetByTopBottom(0, 0, mParentFrame);
- assertInsetByTopBottom(0, 0, mFrame);
+ assertInsetByTopBottom(0, 0, mOutFrames.displayFrame);
+ assertInsetByTopBottom(0, 0, mOutFrames.parentFrame);
+ assertInsetByTopBottom(0, 0, mOutFrames.frame);
}
}
diff --git a/services/tests/wmtests/src/com/android/server/wm/WindowOrganizerTests.java b/services/tests/wmtests/src/com/android/server/wm/WindowOrganizerTests.java
index 25d7334..b4d305b 100644
--- a/services/tests/wmtests/src/com/android/server/wm/WindowOrganizerTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/WindowOrganizerTests.java
@@ -932,7 +932,7 @@
mWm.mAtmService.mTaskOrganizerController.dispatchPendingEvents();
assertNotNull(o.mChangedInfo);
assertNotNull(o.mChangedInfo.pictureInPictureParams);
- final Rational ratio = o.mChangedInfo.pictureInPictureParams.getAspectRatioRational();
+ final Rational ratio = o.mChangedInfo.pictureInPictureParams.getAspectRatio();
assertEquals(3, ratio.getNumerator());
assertEquals(4, ratio.getDenominator());
}
diff --git a/services/tests/wmtests/src/com/android/server/wm/WindowStateTests.java b/services/tests/wmtests/src/com/android/server/wm/WindowStateTests.java
index 6d7895f..6a3aa78 100644
--- a/services/tests/wmtests/src/com/android/server/wm/WindowStateTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/WindowStateTests.java
@@ -504,7 +504,7 @@
assertTrue(win.useBLASTSync());
final SurfaceControl.Transaction drawT = new StubTransaction();
win.prepareDrawHandlers();
- assertTrue(win.finishDrawing(drawT));
+ assertTrue(win.finishDrawing(drawT, Integer.MAX_VALUE));
assertEquals(drawT, handledT[0]);
assertFalse(win.useBLASTSync());
@@ -693,7 +693,7 @@
doThrow(new RemoteException("test")).when(win.mClient).resized(any() /* frames */,
anyBoolean() /* reportDraw */, any() /* mergedConfig */,
anyBoolean() /* forceLayout */, anyBoolean() /* alwaysConsumeSystemBars */,
- anyInt() /* displayId */);
+ anyInt() /* displayId */, anyInt() /* seqId */);
} catch (RemoteException ignored) {
}
win.reportResized();
diff --git a/services/usage/java/com/android/server/usage/UsageStatsService.java b/services/usage/java/com/android/server/usage/UsageStatsService.java
index b9abbf0..366ab09 100644
--- a/services/usage/java/com/android/server/usage/UsageStatsService.java
+++ b/services/usage/java/com/android/server/usage/UsageStatsService.java
@@ -2015,7 +2015,7 @@
== PackageManager.PERMISSION_GRANTED;
}
- private boolean hasPermissions(String callingPackage, String... permissions) {
+ private boolean hasPermissions(String... permissions) {
final int callingUid = Binder.getCallingUid();
if (callingUid == Process.SYSTEM_UID) {
// Caller is the system, so proceed.
@@ -2578,7 +2578,7 @@
String callingPackage) {
final int callingUid = Binder.getCallingUid();
final DevicePolicyManagerInternal dpmInternal = getDpmInternal();
- if (!hasPermissions(callingPackage,
+ if (!hasPermissions(
Manifest.permission.SUSPEND_APPS, Manifest.permission.OBSERVE_APP_USAGE)
&& (dpmInternal == null || !dpmInternal.isActiveSupervisionApp(callingUid))) {
throw new SecurityException("Caller must be the active supervision app or "
@@ -2605,7 +2605,7 @@
public void unregisterAppUsageLimitObserver(int observerId, String callingPackage) {
final int callingUid = Binder.getCallingUid();
final DevicePolicyManagerInternal dpmInternal = getDpmInternal();
- if (!hasPermissions(callingPackage,
+ if (!hasPermissions(
Manifest.permission.SUSPEND_APPS, Manifest.permission.OBSERVE_APP_USAGE)
&& (dpmInternal == null || !dpmInternal.isActiveSupervisionApp(callingUid))) {
throw new SecurityException("Caller must be the active supervision app or "
@@ -2703,8 +2703,7 @@
@Override
public long getLastTimeAnyComponentUsed(String packageName, String callingPackage) {
- if (!hasPermissions(
- callingPackage, android.Manifest.permission.INTERACT_ACROSS_USERS)) {
+ if (!hasPermissions(android.Manifest.permission.INTERACT_ACROSS_USERS)) {
throw new SecurityException("Caller doesn't have INTERACT_ACROSS_USERS permission");
}
if (!hasPermission(callingPackage)) {
@@ -2731,13 +2730,19 @@
throw new IllegalArgumentException("id needs to be >=0");
}
- final int callingUid = Binder.getCallingUid();
- if (!hasPermission(callingPackage)) {
- throw new SecurityException(
- "Caller does not have the permission needed to call this API; "
- + "callingPackage=" + callingPackage
- + ", callingUid=" + callingUid);
+ final int result = getContext().checkCallingOrSelfPermission(
+ android.Manifest.permission.ACCESS_BROADCAST_RESPONSE_STATS);
+ // STOPSHIP (206518114): Temporarily check for PACKAGE_USAGE_STATS permission as well
+ // until the clients switch to using the new permission.
+ if (result != PackageManager.PERMISSION_GRANTED) {
+ if (!hasPermission(callingPackage)) {
+ throw new SecurityException(
+ "Caller does not have the permission needed to call this API; "
+ + "callingPackage=" + callingPackage
+ + ", callingUid=" + Binder.getCallingUid());
+ }
}
+ final int callingUid = Binder.getCallingUid();
userId = ActivityManager.handleIncomingUser(Binder.getCallingPid(), callingUid,
userId, false /* allowAll */, false /* requireFull */,
"queryBroadcastResponseStats" /* name */, callingPackage);
@@ -2757,13 +2762,20 @@
throw new IllegalArgumentException("id needs to be >=0");
}
- final int callingUid = Binder.getCallingUid();
- if (!hasPermission(callingPackage)) {
- throw new SecurityException(
- "Caller does not have the permission needed to call this API; "
- + "callingPackage=" + callingPackage
- + ", callingUid=" + callingUid);
+
+ final int result = getContext().checkCallingOrSelfPermission(
+ android.Manifest.permission.ACCESS_BROADCAST_RESPONSE_STATS);
+ // STOPSHIP (206518114): Temporarily check for PACKAGE_USAGE_STATS permission as well
+ // until the clients switch to using the new permission.
+ if (result != PackageManager.PERMISSION_GRANTED) {
+ if (!hasPermission(callingPackage)) {
+ throw new SecurityException(
+ "Caller does not have the permission needed to call this API; "
+ + "callingPackage=" + callingPackage
+ + ", callingUid=" + Binder.getCallingUid());
+ }
}
+ final int callingUid = Binder.getCallingUid();
userId = ActivityManager.handleIncomingUser(Binder.getCallingPid(), callingUid,
userId, false /* allowAll */, false /* requireFull */,
"clearBroadcastResponseStats" /* name */, callingPackage);
@@ -2775,18 +2787,35 @@
public void clearBroadcastEvents(@NonNull String callingPackage, @UserIdInt int userId) {
Objects.requireNonNull(callingPackage);
- final int callingUid = Binder.getCallingUid();
- if (!hasPermission(callingPackage)) {
- throw new SecurityException(
- "Caller does not have the permission needed to call this API; "
- + "callingPackage=" + callingPackage
- + ", callingUid=" + callingUid);
+ final int result = getContext().checkCallingOrSelfPermission(
+ android.Manifest.permission.ACCESS_BROADCAST_RESPONSE_STATS);
+ // STOPSHIP (206518114): Temporarily check for PACKAGE_USAGE_STATS permission as well
+ // until the clients switch to using the new permission.
+ if (result != PackageManager.PERMISSION_GRANTED) {
+ if (!hasPermission(callingPackage)) {
+ throw new SecurityException(
+ "Caller does not have the permission needed to call this API; "
+ + "callingPackage=" + callingPackage
+ + ", callingUid=" + Binder.getCallingUid());
+ }
}
+ final int callingUid = Binder.getCallingUid();
userId = ActivityManager.handleIncomingUser(Binder.getCallingPid(), callingUid,
userId, false /* allowAll */, false /* requireFull */,
"clearBroadcastResponseStats" /* name */, callingPackage);
mResponseStatsTracker.clearBroadcastEvents(callingUid, userId);
}
+
+ @Override
+ @Nullable
+ public String getAppStandbyConstant(@NonNull String key) {
+ Objects.requireNonNull(key);
+
+ if (!hasPermissions(Manifest.permission.READ_DEVICE_CONFIG)) {
+ throw new SecurityException("Caller doesn't have READ_DEVICE_CONFIG permission");
+ }
+ return mAppStandby.getAppStandbyConstant(key);
+ }
}
void registerAppUsageObserver(int callingUid, int observerId, String[] packages,
diff --git a/services/usb/java/com/android/server/usb/UsbHostManager.java b/services/usb/java/com/android/server/usb/UsbHostManager.java
index a70b0332..dd58d38 100644
--- a/services/usb/java/com/android/server/usb/UsbHostManager.java
+++ b/services/usb/java/com/android/server/usb/UsbHostManager.java
@@ -496,11 +496,13 @@
// MIDI
ArrayList<UsbDirectMidiDevice> midiDevices =
mMidiDevices.remove(deviceAddress);
- for (UsbDirectMidiDevice midiDevice : midiDevices) {
- if (midiDevice != null) {
- Slog.i(TAG, "USB MIDI Device Removed: " + deviceAddress);
- IoUtils.closeQuietly(midiDevice);
+ if (midiDevices != null) {
+ for (UsbDirectMidiDevice midiDevice : midiDevices) {
+ if (midiDevice != null) {
+ IoUtils.closeQuietly(midiDevice);
+ }
}
+ Slog.i(TAG, "USB MIDI Devices Removed: " + deviceAddress);
}
getCurrentUserSettings().usbDeviceRemoved(device);
diff --git a/services/voiceinteraction/java/com/android/server/soundtrigger/SoundTriggerHelper.java b/services/voiceinteraction/java/com/android/server/soundtrigger/SoundTriggerHelper.java
index 24ce7e7..c8bcb83 100644
--- a/services/voiceinteraction/java/com/android/server/soundtrigger/SoundTriggerHelper.java
+++ b/services/voiceinteraction/java/com/android/server/soundtrigger/SoundTriggerHelper.java
@@ -84,6 +84,9 @@
private static final int INVALID_VALUE = Integer.MIN_VALUE;
+ /** Maximum time to wait for a model stop confirmation before giving up. */
+ private static final long STOP_TIMEOUT_MS = 5000;
+
/** The {@link ModuleProperties} for the system, or null if none exists. */
final ModuleProperties mModuleProperties;
@@ -831,7 +834,7 @@
}
if (!event.recognitionStillActive) {
- model.setStopped();
+ model.setStoppedLocked();
}
try {
@@ -918,7 +921,7 @@
MetricsLogger.count(mContext, "sth_recognition_aborted", 1);
ModelData modelData = getModelDataForLocked(event.soundModelHandle);
if (modelData != null && modelData.isModelStarted()) {
- modelData.setStopped();
+ modelData.setStoppedLocked();
try {
modelData.getCallback().onRecognitionPaused();
} catch (DeadObjectException e) {
@@ -972,7 +975,7 @@
}
if (!event.recognitionStillActive) {
- modelData.setStopped();
+ modelData.setStoppedLocked();
}
try {
@@ -1200,7 +1203,7 @@
if (modelData.isModelStarted()) {
Slog.d(TAG, "Stopping previously started dangling model " + modelData.getHandle());
if (mModule.stopRecognition(modelData.getHandle()) == STATUS_OK) {
- modelData.setStopped();
+ modelData.setStoppedLocked();
modelData.setRequested(false);
} else {
Slog.e(TAG, "Failed to stop model " + modelData.getHandle());
@@ -1249,7 +1252,7 @@
private ModelData getOrCreateGenericModelDataLocked(UUID modelId) {
ModelData modelData = mModelDataMap.get(modelId);
if (modelData == null) {
- modelData = ModelData.createGenericModelData(modelId);
+ modelData = createGenericModelData(modelId);
mModelDataMap.put(modelId, modelData);
} else if (!modelData.isGenericModel()) {
Slog.e(TAG, "UUID already used for non-generic model.");
@@ -1281,7 +1284,7 @@
mKeyphraseUuidMap.remove(keyphraseId);
mModelDataMap.remove(modelId);
mKeyphraseUuidMap.put(keyphraseId, modelId);
- ModelData modelData = ModelData.createKeyphraseModelData(modelId);
+ ModelData modelData = createKeyphraseModelData(modelId);
mModelDataMap.put(modelId, modelData);
return modelData;
}
@@ -1413,18 +1416,26 @@
Slog.w(TAG, "RemoteException in onError", e);
}
}
- } else {
- modelData.setStopped();
- MetricsLogger.count(mContext, "sth_stop_recognition_success", 1);
- // Notify of pause if needed.
- if (notify) {
- try {
- callback.onRecognitionPaused();
- } catch (DeadObjectException e) {
- forceStopAndUnloadModelLocked(modelData, e);
- } catch (RemoteException e) {
- Slog.w(TAG, "RemoteException in onRecognitionPaused", e);
- }
+ return status;
+ }
+
+ // Wait for model to be stopped.
+ try {
+ modelData.waitStoppedLocked(STOP_TIMEOUT_MS);
+ } catch (InterruptedException e) {
+ Slog.e(TAG, "Didn't receive model stop callback");
+ return SoundTrigger.STATUS_ERROR;
+ }
+
+ MetricsLogger.count(mContext, "sth_stop_recognition_success", 1);
+ // Notify of pause if needed.
+ if (notify) {
+ try {
+ callback.onRecognitionPaused();
+ } catch (DeadObjectException e) {
+ forceStopAndUnloadModelLocked(modelData, e);
+ } catch (RemoteException e) {
+ Slog.w(TAG, "RemoteException in onRecognitionPaused", e);
}
}
if (DBG) {
@@ -1459,7 +1470,7 @@
// This class encapsulates the callbacks, state, handles and any other information that
// represents a model.
- private static class ModelData {
+ private class ModelData {
// Model not loaded (and hence not started).
static final int MODEL_NOTLOADED = 0;
@@ -1516,17 +1527,9 @@
mModelType = modelType;
}
- static ModelData createKeyphraseModelData(UUID modelId) {
- return new ModelData(modelId, SoundModel.TYPE_KEYPHRASE);
- }
-
- static ModelData createGenericModelData(UUID modelId) {
- return new ModelData(modelId, SoundModel.TYPE_GENERIC_SOUND);
- }
-
// Note that most of the functionality in this Java class will not work for
// SoundModel.TYPE_UNKNOWN nevertheless we have it since lower layers support it.
- static ModelData createModelDataOfUnknownType(UUID modelId) {
+ ModelData createModelDataOfUnknownType(UUID modelId) {
return new ModelData(modelId, SoundModel.TYPE_UNKNOWN);
}
@@ -1550,8 +1553,20 @@
mModelState = MODEL_STARTED;
}
- synchronized void setStopped() {
+ synchronized void setStoppedLocked() {
mModelState = MODEL_LOADED;
+ mLock.notifyAll();
+ }
+
+ void waitStoppedLocked(long timeoutMs) throws InterruptedException {
+ long deadline = System.currentTimeMillis() + timeoutMs;
+ while (mModelState == MODEL_STARTED) {
+ long waitTime = deadline - System.currentTimeMillis();
+ if (waitTime <= 0) {
+ throw new InterruptedException();
+ }
+ mLock.wait(waitTime);
+ }
}
synchronized void setLoaded() {
@@ -1571,6 +1586,7 @@
mRecognitionConfig = null;
mRequested = false;
mCallback = null;
+ notifyAll();
}
synchronized void clearCallback() {
@@ -1675,4 +1691,12 @@
return "Model type: " + type + "\n";
}
}
+
+ ModelData createKeyphraseModelData(UUID modelId) {
+ return new ModelData(modelId, SoundModel.TYPE_KEYPHRASE);
+ }
+
+ ModelData createGenericModelData(UUID modelId) {
+ return new ModelData(modelId, SoundModel.TYPE_GENERIC_SOUND);
+ }
}
diff --git a/services/voiceinteraction/java/com/android/server/voiceinteraction/HotwordDetectionConnection.java b/services/voiceinteraction/java/com/android/server/voiceinteraction/HotwordDetectionConnection.java
index 5a95210..d527a23 100644
--- a/services/voiceinteraction/java/com/android/server/voiceinteraction/HotwordDetectionConnection.java
+++ b/services/voiceinteraction/java/com/android/server/voiceinteraction/HotwordDetectionConnection.java
@@ -20,6 +20,7 @@
import static android.Manifest.permission.RECORD_AUDIO;
import static android.service.voice.HotwordDetectionService.AUDIO_SOURCE_EXTERNAL;
import static android.service.voice.HotwordDetectionService.AUDIO_SOURCE_MICROPHONE;
+import static android.service.voice.HotwordDetectionService.INITIALIZATION_STATUS_SUCCESS;
import static android.service.voice.HotwordDetectionService.INITIALIZATION_STATUS_UNKNOWN;
import static android.service.voice.HotwordDetectionService.KEY_INITIALIZATION_STATUS;
@@ -67,6 +68,7 @@
import android.os.RemoteException;
import android.os.ServiceManager;
import android.os.SharedMemory;
+import android.provider.DeviceConfig;
import android.service.voice.HotwordDetectedResult;
import android.service.voice.HotwordDetectionService;
import android.service.voice.HotwordDetector;
@@ -110,12 +112,20 @@
private static final String TAG = "HotwordDetectionConnection";
static final boolean DEBUG = false;
+ private static final String KEY_RESTART_PERIOD_IN_SECONDS = "restart_period_in_seconds";
// TODO: These constants need to be refined.
private static final long VALIDATION_TIMEOUT_MILLIS = 4000;
private static final long MAX_UPDATE_TIMEOUT_MILLIS = 6000;
private static final Duration MAX_UPDATE_TIMEOUT_DURATION =
Duration.ofMillis(MAX_UPDATE_TIMEOUT_MILLIS);
private static final long RESET_DEBUG_HOTWORD_LOGGING_TIMEOUT_MILLIS = 60 * 60 * 1000; // 1 hour
+ /**
+ * Time after which each HotwordDetectionService process is stopped and replaced by a new one.
+ * 0 indicates no restarts.
+ */
+ private static final int RESTART_PERIOD_SECONDS =
+ DeviceConfig.getInt(DeviceConfig.NAMESPACE_VOICE_INTERACTION,
+ KEY_RESTART_PERIOD_IN_SECONDS, 0);
private static final int MAX_ISOLATED_PROCESS_NUMBER = 10;
// Hotword metrics
@@ -134,6 +144,7 @@
// TODO: This may need to be a Handler(looper)
private final ScheduledExecutorService mScheduledExecutorService =
Executors.newSingleThreadScheduledExecutor();
+ @Nullable private final ScheduledFuture<?> mCancellationTaskFuture;
private final AtomicBoolean mUpdateStateAfterStartFinished = new AtomicBoolean(false);
private final IBinder.DeathRecipient mAudioServerDeathRecipient = this::audioServerDied;
private final @NonNull ServiceConnectionFactory mServiceConnectionFactory;
@@ -150,7 +161,6 @@
private IMicrophoneHotwordDetectionVoiceInteractionCallback mSoftwareCallback;
private Instant mLastRestartInstant;
- private ScheduledFuture<?> mCancellationTaskFuture;
private ScheduledFuture<?> mCancellationKeyPhraseDetectionFuture;
private ScheduledFuture<?> mDebugHotwordLoggingTimeoutFuture = null;
@@ -196,16 +206,20 @@
mLastRestartInstant = Instant.now();
updateStateAfterProcessStart(options, sharedMemory);
- // TODO(volnov): we need to be smarter here, e.g. schedule it a bit more often, but wait
- // until the current session is closed.
- mCancellationTaskFuture = mScheduledExecutorService.scheduleAtFixedRate(() -> {
- Slog.v(TAG, "Time to restart the process, TTL has passed");
- synchronized (mLock) {
- restartProcessLocked();
- HotwordMetricsLogger.writeServiceRestartEvent(mDetectorType,
- HOTWORD_DETECTION_SERVICE_RESTARTED__REASON__SCHEDULE);
- }
- }, 30, 30, TimeUnit.MINUTES);
+ if (RESTART_PERIOD_SECONDS <= 0) {
+ mCancellationTaskFuture = null;
+ } else {
+ // TODO(volnov): we need to be smarter here, e.g. schedule it a bit more often, but wait
+ // until the current session is closed.
+ mCancellationTaskFuture = mScheduledExecutorService.scheduleAtFixedRate(() -> {
+ Slog.v(TAG, "Time to restart the process, TTL has passed");
+ synchronized (mLock) {
+ restartProcessLocked();
+ HotwordMetricsLogger.writeServiceRestartEvent(mDetectorType,
+ HOTWORD_DETECTION_SERVICE_RESTARTED__REASON__SCHEDULE);
+ }
+ }, RESTART_PERIOD_SECONDS, RESTART_PERIOD_SECONDS, TimeUnit.SECONDS);
+ }
}
private void initAudioFlingerLocked() {
@@ -317,15 +331,16 @@
return new Pair<>(INITIALIZATION_STATUS_UNKNOWN, METRICS_INIT_UNKNOWN_NO_VALUE);
}
int status = bundle.getInt(KEY_INITIALIZATION_STATUS, INITIALIZATION_STATUS_UNKNOWN);
- if (status > HotwordDetectionService.getMaxCustomInitializationStatus()
- && status != INITIALIZATION_STATUS_UNKNOWN) {
+ if (status > HotwordDetectionService.getMaxCustomInitializationStatus()) {
return new Pair<>(INITIALIZATION_STATUS_UNKNOWN,
- METRICS_INIT_UNKNOWN_OVER_MAX_CUSTOM_VALUE);
+ status == INITIALIZATION_STATUS_UNKNOWN
+ ? METRICS_INIT_UNKNOWN_NO_VALUE
+ : METRICS_INIT_UNKNOWN_OVER_MAX_CUSTOM_VALUE);
}
// TODO: should guard against negative here
- int metricsResult = status == INITIALIZATION_STATUS_UNKNOWN
- ? METRICS_INIT_CALLBACK_STATE_ERROR
- : METRICS_INIT_CALLBACK_STATE_SUCCESS;
+ int metricsResult = status == INITIALIZATION_STATUS_SUCCESS
+ ? METRICS_INIT_CALLBACK_STATE_SUCCESS
+ : METRICS_INIT_CALLBACK_STATE_ERROR;
return new Pair<>(status, metricsResult);
}
@@ -346,7 +361,9 @@
removeServiceUidForAudioPolicy(mIdentity.getIsolatedUid());
}
mIdentity = null;
- mCancellationTaskFuture.cancel(/* may interrupt */ true);
+ if (mCancellationTaskFuture != null) {
+ mCancellationTaskFuture.cancel(/* may interrupt */ true);
+ }
if (mAudioFlinger != null) {
mAudioFlinger.unlinkToDeath(mAudioServerDeathRecipient, /* flags= */ 0);
}
@@ -764,6 +781,7 @@
}
public void dump(String prefix, PrintWriter pw) {
+ pw.print(prefix); pw.print("RESTART_PERIOD_SECONDS="); pw.println(RESTART_PERIOD_SECONDS);
pw.print(prefix);
pw.print("mBound=" + mRemoteHotwordDetectionService.isBound());
pw.print(", mValidatingDspTrigger=" + mValidatingDspTrigger);
diff --git a/telephony/java/android/telephony/CarrierConfigManager.java b/telephony/java/android/telephony/CarrierConfigManager.java
index 837cf8b..cff90bb 100644
--- a/telephony/java/android/telephony/CarrierConfigManager.java
+++ b/telephony/java/android/telephony/CarrierConfigManager.java
@@ -504,7 +504,12 @@
/** Control whether users can choose a network operator. */
public static final String KEY_OPERATOR_SELECTION_EXPAND_BOOL = "operator_selection_expand_bool";
- /** Used in Cellular Network Settings for preferred network type. */
+ /**
+ * Used in the Preferred Network Types menu to determine if the 2G option is displayed.
+ * Value defaults to false as of Android T to discourage the use of insecure 2G protocols.
+ *
+ * @see #KEY_HIDE_ENABLE_2G
+ */
public static final String KEY_PREFER_2G_BOOL = "prefer_2g_bool";
/**
@@ -8594,7 +8599,7 @@
sDefaults.putBoolean(KEY_IGNORE_SIM_NETWORK_LOCKED_EVENTS_BOOL, false);
sDefaults.putBoolean(KEY_MDN_IS_ADDITIONAL_VOICEMAIL_NUMBER_BOOL, false);
sDefaults.putBoolean(KEY_OPERATOR_SELECTION_EXPAND_BOOL, true);
- sDefaults.putBoolean(KEY_PREFER_2G_BOOL, true);
+ sDefaults.putBoolean(KEY_PREFER_2G_BOOL, false);
sDefaults.putBoolean(KEY_4G_ONLY_BOOL, false);
sDefaults.putBoolean(KEY_SHOW_APN_SETTING_CDMA_BOOL, false);
sDefaults.putBoolean(KEY_SHOW_CDMA_CHOICES_BOOL, false);
diff --git a/telephony/java/android/telephony/TelephonyManager.java b/telephony/java/android/telephony/TelephonyManager.java
index 5ef22de..f3139a7 100644
--- a/telephony/java/android/telephony/TelephonyManager.java
+++ b/telephony/java/android/telephony/TelephonyManager.java
@@ -8352,24 +8352,6 @@
}
/**
- * Get P-CSCF address from PCO after data connection is established or modified.
- * @param apnType the apnType, "ims" for IMS APN, "emergency" for EMERGENCY APN
- * @return array of P-CSCF address
- * @hide
- */
- public String[] getPcscfAddress(String apnType) {
- try {
- ITelephony telephony = getITelephony();
- if (telephony == null)
- return new String[0];
- return telephony.getPcscfAddress(apnType, getOpPackageName(), getAttributionTag());
- } catch (RemoteException e) {
- return new String[0];
- }
- }
-
-
- /**
* Resets the {@link android.telephony.ims.ImsService} associated with the specified sim slot.
* Used by diagnostic apps to force the IMS stack to be disabled and re-enabled in an effort to
* recover from scenarios where the {@link android.telephony.ims.ImsService} gets in to a bad
@@ -9833,15 +9815,7 @@
@SystemApi
@RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
public @Nullable String getCarrierServicePackageName() {
- // TODO(b/205736323) plumb this through to CarrierPrivilegesTracker, which will cache the
- // value instead of re-querying every time.
- List<String> carrierServicePackages =
- getCarrierPackageNamesForIntent(
- new Intent(CarrierService.CARRIER_SERVICE_INTERFACE));
- if (carrierServicePackages != null && !carrierServicePackages.isEmpty()) {
- return carrierServicePackages.get(0);
- }
- return null;
+ return getCarrierServicePackageNameForLogicalSlot(getPhoneId());
}
/**
@@ -9858,13 +9832,15 @@
@SystemApi
@RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
public @Nullable String getCarrierServicePackageNameForLogicalSlot(int logicalSlotIndex) {
- // TODO(b/205736323) plumb this through to CarrierPrivilegesTracker, which will cache the
- // value instead of re-querying every time.
- List<String> carrierServicePackages =
- getCarrierPackageNamesForIntentAndPhone(
- new Intent(CarrierService.CARRIER_SERVICE_INTERFACE), logicalSlotIndex);
- if (carrierServicePackages != null && !carrierServicePackages.isEmpty()) {
- return carrierServicePackages.get(0);
+ try {
+ ITelephony telephony = getITelephony();
+ if (telephony != null) {
+ return telephony.getCarrierServicePackageNameForLogicalSlot(logicalSlotIndex);
+ }
+ } catch (RemoteException ex) {
+ Rlog.e(TAG, "getCarrierServicePackageNameForLogicalSlot RemoteException", ex);
+ } catch (NullPointerException ex) {
+ Rlog.e(TAG, "getCarrierServicePackageNameForLogicalSlot NPE", ex);
}
return null;
}
diff --git a/telephony/java/android/telephony/data/ApnSetting.java b/telephony/java/android/telephony/data/ApnSetting.java
index fc94ebf..8143da5 100644
--- a/telephony/java/android/telephony/data/ApnSetting.java
+++ b/telephony/java/android/telephony/data/ApnSetting.java
@@ -549,7 +549,6 @@
* Returns the profile id to which the APN saved in modem.
*
* @return the profile id of the APN
- * @hide
*/
public int getProfileId() {
return mProfileId;
@@ -558,8 +557,7 @@
/**
* Returns if the APN setting is persistent on the modem.
*
- * @return is the APN setting to be set in modem
- * @hide
+ * @return {@code true} if the APN setting is persistent on the modem.
*/
public boolean isPersistent() {
return mPersistent;
@@ -1103,8 +1101,10 @@
sb.append(", ").append(MVNO_TYPE_INT_MAP.get(mMvnoType));
sb.append(", ").append(mMvnoMatchData);
sb.append(", ").append(mPermanentFailed);
- sb.append(", ").append(mNetworkTypeBitmask);
- sb.append(", ").append(mLingeringNetworkTypeBitmask);
+ sb.append(", ").append(TelephonyManager.convertNetworkTypeBitmaskToString(
+ mNetworkTypeBitmask));
+ sb.append(", ").append(TelephonyManager.convertNetworkTypeBitmaskToString(
+ mLingeringNetworkTypeBitmask));
sb.append(", ").append(mApnSetId);
sb.append(", ").append(mCarrierId);
sb.append(", ").append(mSkip464Xlat);
diff --git a/telephony/java/android/telephony/data/DataService.java b/telephony/java/android/telephony/data/DataService.java
index 892eb29..bd346d5 100644
--- a/telephony/java/android/telephony/data/DataService.java
+++ b/telephony/java/android/telephony/data/DataService.java
@@ -31,6 +31,7 @@
import android.os.Looper;
import android.os.Message;
import android.os.RemoteException;
+import android.telephony.AccessNetworkConstants.RadioAccessNetworkType;
import android.util.Log;
import android.util.SparseArray;
@@ -166,7 +167,8 @@
* link properties of the existing data connection, otherwise null.
* @param callback The result callback for this request.
*/
- public void setupDataCall(int accessNetworkType, @NonNull DataProfile dataProfile,
+ public void setupDataCall(
+ @RadioAccessNetworkType int accessNetworkType, @NonNull DataProfile dataProfile,
boolean isRoaming, boolean allowRoaming,
@SetupDataReason int reason, @Nullable LinkProperties linkProperties,
@NonNull DataServiceCallback callback) {
@@ -214,7 +216,8 @@
* for example, a zero-rating slice.
* @param callback The result callback for this request.
*/
- public void setupDataCall(int accessNetworkType, @NonNull DataProfile dataProfile,
+ public void setupDataCall(
+ @RadioAccessNetworkType int accessNetworkType, @NonNull DataProfile dataProfile,
boolean isRoaming, boolean allowRoaming,
@SetupDataReason int reason,
@Nullable LinkProperties linkProperties,
@@ -294,6 +297,9 @@
* with reason {@link DataService.REQUEST_REASON_HANDOVER}. The target transport now owns
* the transferred resources and is responsible for releasing them.
*
+ * <p/>
+ * Note that the callback will be executed on binder thread.
+ *
* @param cid The identifier of the data call which is provided in {@link DataCallResponse}
* @param callback The result callback for this request.
*
@@ -322,6 +328,9 @@
* </li>
* </ul>
*
+ * <p/>
+ * Note that the callback will be executed on binder thread.
+ *
* @param cid The identifier of the data call which is provided in {@link DataCallResponse}
* @param callback The result callback for this request.
*
diff --git a/telephony/java/android/telephony/data/EpsBearerQosSessionAttributes.java b/telephony/java/android/telephony/data/EpsBearerQosSessionAttributes.java
index fe44530..5ffee56 100644
--- a/telephony/java/android/telephony/data/EpsBearerQosSessionAttributes.java
+++ b/telephony/java/android/telephony/data/EpsBearerQosSessionAttributes.java
@@ -32,7 +32,12 @@
import java.util.Objects;
/**
- * Provides Qos attributes of an EPS bearer.
+ * Provides QOS attributes of an EPS bearer.
+ *
+ * <p> The dedicated EPS bearer along with QOS is allocated by the LTE network and notified to the
+ * device. The Telephony framework creates the {@link EpsBearerQosSessionAttributes} object which
+ * represents the QOS of the dedicated bearer and notifies the same to applications via
+ * {@link QosCallback}.
*
* {@hide}
*/
diff --git a/telephony/java/com/android/internal/telephony/ITelephony.aidl b/telephony/java/com/android/internal/telephony/ITelephony.aidl
index dc96b35..e3ebb9a 100644
--- a/telephony/java/com/android/internal/telephony/ITelephony.aidl
+++ b/telephony/java/com/android/internal/telephony/ITelephony.aidl
@@ -978,14 +978,6 @@
boolean isManualNetworkSelectionAllowed(int subId);
/**
- * Get P-CSCF address from PCO after data connection is established or modified.
- * @param apnType the apnType, "ims" for IMS APN, "emergency" for EMERGENCY APN
- * @param callingPackage The package making the call.
- * @param callingFeatureId The feature in the package.
- */
- String[] getPcscfAddress(String apnType, String callingPackage, String callingFeatureId);
-
- /**
* Set IMS registration state
*/
void setImsRegistrationState(boolean registered);
@@ -2549,4 +2541,15 @@
* PhoneAccount#CAPABILITY_VOICE_CALLING_AVAILABLE.
*/
void setVoiceServiceStateOverride(int subId, boolean hasService, String callingPackage);
+
+ /**
+ * Returns the package name that provides the {@link CarrierService} implementation for the
+ * specified {@code logicalSlotIndex}, or {@code null} if no package with carrier privileges
+ * declares one.
+ *
+ * @param logicalSlotIndex The slot index to fetch the {@link CarrierService} package for
+ * @return The system-selected package that provides the {@link CarrierService} implementation
+ * for the slot, or {@code null} if none is resolved
+ */
+ String getCarrierServicePackageNameForLogicalSlot(int logicalSlotIndex);
}
diff --git a/tests/BandwidthTests/src/com/android/tests/bandwidthenforcement/BandwidthEnforcementTestService.java b/tests/BandwidthTests/src/com/android/tests/bandwidthenforcement/BandwidthEnforcementTestService.java
index 35f1e58..644d450 100644
--- a/tests/BandwidthTests/src/com/android/tests/bandwidthenforcement/BandwidthEnforcementTestService.java
+++ b/tests/BandwidthTests/src/com/android/tests/bandwidthenforcement/BandwidthEnforcementTestService.java
@@ -24,6 +24,8 @@
import android.os.Environment;
import android.util.Log;
+import libcore.io.Streams;
+
import java.io.BufferedWriter;
import java.io.ByteArrayOutputStream;
import java.io.File;
@@ -37,8 +39,6 @@
import java.net.URL;
import java.util.Random;
-import libcore.io.Streams;
-
/*
* Test Service that tries to connect to the web via different methods and outputs the results to
* the log and a output file.
@@ -146,7 +146,7 @@
final ConnectivityManager mCM = context.getSystemService(ConnectivityManager.class);
final Network network = mCM.getActiveNetwork();
- if (client.requestTime("0.pool.ntp.org", 10000, network)) {
+ if (client.requestTime("0.pool.ntp.org", SntpClient.STANDARD_NTP_PORT, 10000, network)) {
return true;
}
return false;
diff --git a/tests/TrustTests/AndroidManifest.xml b/tests/TrustTests/AndroidManifest.xml
index 68bc1f69..8b4cbfd 100644
--- a/tests/TrustTests/AndroidManifest.xml
+++ b/tests/TrustTests/AndroidManifest.xml
@@ -68,6 +68,16 @@
<action android:name="android.service.trust.TrustAgentService" />
</intent-filter>
</service>
+
+ <service
+ android:name=".TemporaryAndRenewableTrustAgent"
+ android:exported="true"
+ android:label="Test Agent"
+ android:permission="android.permission.BIND_TRUST_AGENT">
+ <intent-filter>
+ <action android:name="android.service.trust.TrustAgentService" />
+ </intent-filter>
+ </service>
</application>
<!-- self-instrumenting test package. -->
diff --git a/tests/TrustTests/src/android/trust/test/GrantAndRevokeTrustTest.kt b/tests/TrustTests/src/android/trust/test/GrantAndRevokeTrustTest.kt
index 790afd3..af7a98c 100644
--- a/tests/TrustTests/src/android/trust/test/GrantAndRevokeTrustTest.kt
+++ b/tests/TrustTests/src/android/trust/test/GrantAndRevokeTrustTest.kt
@@ -60,7 +60,6 @@
@Test
fun sleepingDeviceWithoutGrantLocksDevice() {
uiDevice.sleep()
- await()
lockStateTrackingRule.assertLocked()
}
@@ -69,7 +68,6 @@
fun grantKeepsDeviceUnlocked() {
trustAgentRule.agent.grantTrust(GRANT_MESSAGE, 10000, 0)
uiDevice.sleep()
- await()
lockStateTrackingRule.assertUnlocked()
}
@@ -80,7 +78,6 @@
await()
uiDevice.sleep()
trustAgentRule.agent.revokeTrust()
- await()
lockStateTrackingRule.assertLocked()
}
diff --git a/tests/TrustTests/src/android/trust/test/LockUserTest.kt b/tests/TrustTests/src/android/trust/test/LockUserTest.kt
index 8f200a6..a7dd41ad 100644
--- a/tests/TrustTests/src/android/trust/test/LockUserTest.kt
+++ b/tests/TrustTests/src/android/trust/test/LockUserTest.kt
@@ -24,7 +24,6 @@
import android.util.Log
import androidx.test.ext.junit.rules.ActivityScenarioRule
import androidx.test.ext.junit.runners.AndroidJUnit4
-import com.google.common.truth.Truth.assertThat
import org.junit.Rule
import org.junit.Test
import org.junit.rules.RuleChain
@@ -52,9 +51,8 @@
fun lockUser_locksTheDevice() {
Log.i(TAG, "Locking user")
trustAgentRule.agent.lockUser()
- await()
- assertThat(lockStateTrackingRule.lockState.locked).isTrue()
+ lockStateTrackingRule.assertLocked()
}
companion object {
diff --git a/tests/TrustTests/src/android/trust/test/TemporaryAndRenewableTrustTest.kt b/tests/TrustTests/src/android/trust/test/TemporaryAndRenewableTrustTest.kt
new file mode 100644
index 0000000..14c227b
--- /dev/null
+++ b/tests/TrustTests/src/android/trust/test/TemporaryAndRenewableTrustTest.kt
@@ -0,0 +1,124 @@
+/*
+ * 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.trust.test
+
+import android.service.trust.TrustAgentService.FLAG_GRANT_TRUST_TEMPORARY_AND_RENEWABLE
+import android.trust.BaseTrustAgentService
+import android.trust.TrustTestActivity
+import android.trust.test.lib.LockStateTrackingRule
+import android.trust.test.lib.ScreenLockRule
+import android.trust.test.lib.TrustAgentRule
+import androidx.test.ext.junit.rules.ActivityScenarioRule
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import androidx.test.platform.app.InstrumentationRegistry.getInstrumentation
+import androidx.test.uiautomator.UiDevice
+import org.junit.Before
+import org.junit.Rule
+import org.junit.Test
+import org.junit.rules.RuleChain
+import org.junit.runner.RunWith
+
+/**
+ * Test for testing revokeTrust & grantTrust for renewable trust.
+ *
+ * atest TrustTests:TemporaryAndRenewableTrustTest
+ */
+@RunWith(AndroidJUnit4::class)
+class TemporaryAndRenewableTrustTest {
+ private val uiDevice = UiDevice.getInstance(getInstrumentation())
+ private val activityScenarioRule = ActivityScenarioRule(TrustTestActivity::class.java)
+ private val lockStateTrackingRule = LockStateTrackingRule()
+ private val trustAgentRule = TrustAgentRule<TemporaryAndRenewableTrustAgent>()
+
+ @get:Rule
+ val rule: RuleChain = RuleChain
+ .outerRule(activityScenarioRule)
+ .around(ScreenLockRule())
+ .around(lockStateTrackingRule)
+ .around(trustAgentRule)
+
+ @Before
+ fun manageTrust() {
+ trustAgentRule.agent.setManagingTrust(true)
+ }
+
+ // This test serves a baseline for Grant tests, verifying that the default behavior of the
+ // device is to lock when put to sleep
+ @Test
+ fun sleepingDeviceWithoutGrantLocksDevice() {
+ uiDevice.sleep()
+
+ lockStateTrackingRule.assertLocked()
+ }
+
+ @Test
+ fun grantTrustLockedDevice_deviceStaysLocked() {
+ uiDevice.sleep()
+ lockStateTrackingRule.assertLocked()
+
+ trustAgentRule.agent.grantTrust(GRANT_MESSAGE, 0, FLAG_GRANT_TRUST_TEMPORARY_AND_RENEWABLE)
+ uiDevice.wakeUp()
+
+ lockStateTrackingRule.assertLocked()
+ }
+
+ @Test
+ fun grantTrustUnlockedDevice_deviceLocksOnScreenOff() {
+ trustAgentRule.agent.grantTrust(GRANT_MESSAGE, 0, FLAG_GRANT_TRUST_TEMPORARY_AND_RENEWABLE)
+ uiDevice.sleep()
+
+ lockStateTrackingRule.assertLocked()
+ }
+
+ @Test
+ fun grantTrustLockedDevice_grantTrustOnLockedDeviceUnlocksDevice() {
+ trustAgentRule.agent.grantTrust(GRANT_MESSAGE, 0, FLAG_GRANT_TRUST_TEMPORARY_AND_RENEWABLE)
+ uiDevice.sleep()
+
+ lockStateTrackingRule.assertLocked()
+
+ trustAgentRule.agent.grantTrust(GRANT_MESSAGE, 0, FLAG_GRANT_TRUST_TEMPORARY_AND_RENEWABLE)
+ uiDevice.wakeUp()
+
+ lockStateTrackingRule.assertUnlocked()
+ }
+
+ @Test
+ fun grantTrustLockedDevice_revokeTrustPreventsSubsequentUnlock() {
+ trustAgentRule.agent.grantTrust(GRANT_MESSAGE, 0, FLAG_GRANT_TRUST_TEMPORARY_AND_RENEWABLE)
+ uiDevice.sleep()
+
+ lockStateTrackingRule.assertLocked()
+
+ trustAgentRule.agent.revokeTrust()
+ await(500)
+ uiDevice.wakeUp()
+ await(500)
+
+ trustAgentRule.agent.grantTrust(GRANT_MESSAGE, 0, FLAG_GRANT_TRUST_TEMPORARY_AND_RENEWABLE)
+
+ lockStateTrackingRule.assertLocked()
+ }
+
+ companion object {
+ private const val TAG = "TemporaryAndRenewableTrustTest"
+ private const val GRANT_MESSAGE = "granted by test"
+ private fun await(millis: Long) = Thread.sleep(millis)
+ }
+}
+
+class TemporaryAndRenewableTrustAgent : BaseTrustAgentService()
diff --git a/tests/TrustTests/src/android/trust/test/lib/LockStateTrackingRule.kt b/tests/TrustTests/src/android/trust/test/lib/LockStateTrackingRule.kt
index 0023af8..834f212 100644
--- a/tests/TrustTests/src/android/trust/test/lib/LockStateTrackingRule.kt
+++ b/tests/TrustTests/src/android/trust/test/lib/LockStateTrackingRule.kt
@@ -52,8 +52,29 @@
}
}
- fun assertLocked() = assertThat(lockState.locked).isTrue()
- fun assertUnlocked() = assertThat(lockState.locked).isFalse()
+ fun assertLocked() {
+ val maxWaits = 50
+ var waitCount = 0
+
+ while ((lockState.locked == false) && waitCount < maxWaits) {
+ Log.i(TAG, "phone still locked, wait 50ms more ($waitCount)")
+ Thread.sleep(50)
+ waitCount++
+ }
+ assertThat(lockState.locked).isTrue()
+ }
+
+ fun assertUnlocked() {
+ val maxWaits = 50
+ var waitCount = 0
+
+ while ((lockState.locked == true) && waitCount < maxWaits) {
+ Log.i(TAG, "phone still unlocked, wait 50ms more ($waitCount)")
+ Thread.sleep(50)
+ waitCount++
+ }
+ assertThat(lockState.locked).isFalse()
+ }
inner class Listener : TrustListener {
override fun onTrustChanged(
diff --git a/tools/traceinjection/Android.bp b/tools/traceinjection/Android.bp
new file mode 100644
index 0000000..1395c5f
--- /dev/null
+++ b/tools/traceinjection/Android.bp
@@ -0,0 +1,49 @@
+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"],
+}
+
+java_binary_host {
+ name: "traceinjection",
+ manifest: "manifest.txt",
+ srcs: ["src/**/*.java"],
+ static_libs: [
+ "asm-7.0",
+ "asm-commons-7.0",
+ "asm-tree-7.0",
+ "asm-analysis-7.0",
+ "guava-21.0",
+ ],
+}
+
+java_library_host {
+ name: "TraceInjectionTests-Uninjected",
+ srcs: ["test/**/*.java"],
+ static_libs: [
+ "junit",
+ ],
+}
+
+java_genrule_host {
+ name: "TraceInjectionTests-Injected",
+ srcs: [":TraceInjectionTests-Uninjected"],
+ tools: ["traceinjection"],
+ cmd: "$(location traceinjection) " +
+ " --annotation \"com/android/traceinjection/Trace\"" +
+ " --start \"com/android/traceinjection/InjectionTests.traceStart\"" +
+ " --end \"com/android/traceinjection/InjectionTests.traceEnd\"" +
+ " -o $(out) " +
+ " -i $(in)",
+ out: ["TraceInjectionTests-Injected.jar"],
+}
+
+java_test_host {
+ name: "TraceInjectionTests",
+ static_libs: [
+ "TraceInjectionTests-Injected",
+ ],
+}
diff --git a/tools/traceinjection/manifest.txt b/tools/traceinjection/manifest.txt
new file mode 100644
index 0000000..7f4ee1d
--- /dev/null
+++ b/tools/traceinjection/manifest.txt
@@ -0,0 +1 @@
+Main-Class: com.android.traceinjection.Main
diff --git a/tools/traceinjection/src/com/android/traceinjection/Main.java b/tools/traceinjection/src/com/android/traceinjection/Main.java
new file mode 100644
index 0000000..190df81
--- /dev/null
+++ b/tools/traceinjection/src/com/android/traceinjection/Main.java
@@ -0,0 +1,121 @@
+/*
+ * 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.traceinjection;
+
+import org.objectweb.asm.ClassReader;
+import org.objectweb.asm.ClassWriter;
+
+import java.io.BufferedInputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.util.Enumeration;
+import java.util.zip.ZipEntry;
+import java.util.zip.ZipFile;
+import java.util.zip.ZipOutputStream;
+
+public class Main {
+ public static void main(String[] args) throws IOException {
+ String inJar = null;
+ String outJar = null;
+ String annotation = null;
+ String traceStart = null;
+ String traceEnd = null;
+
+ // All arguments require a value currently, so just make sure we have an even number and
+ // then process them all two at a time.
+ if (args.length % 2 != 0) {
+ throw new IllegalArgumentException("Argument is missing corresponding value");
+ }
+ for (int i = 0; i < args.length - 1; i += 2) {
+ final String arg = args[i].trim();
+ final String argValue = args[i + 1].trim();
+ if ("-i".equals(arg)) {
+ inJar = argValue;
+ } else if ("-o".equals(arg)) {
+ outJar = argValue;
+ } else if ("--annotation".equals(arg)) {
+ annotation = argValue;
+ } else if ("--start".equals(arg)) {
+ traceStart = argValue;
+ } else if ("--end".equals(arg)) {
+ traceEnd = argValue;
+ } else {
+ throw new IllegalArgumentException("Unknown argument: " + arg);
+ }
+ }
+
+ if (inJar == null) {
+ throw new IllegalArgumentException("input jar is required");
+ }
+
+ if (outJar == null) {
+ throw new IllegalArgumentException("output jar is required");
+ }
+
+ if (annotation == null) {
+ throw new IllegalArgumentException("trace annotation is required");
+ }
+
+ if (traceStart == null) {
+ throw new IllegalArgumentException("start trace method is required");
+ }
+
+ if (traceEnd == null) {
+ throw new IllegalArgumentException("end trace method is required");
+ }
+
+ TraceInjectionConfiguration params =
+ new TraceInjectionConfiguration(annotation, traceStart, traceEnd);
+
+ try (
+ ZipFile zipSrc = new ZipFile(inJar);
+ ZipOutputStream zos = new ZipOutputStream(new FileOutputStream(outJar));
+ ) {
+ Enumeration<? extends ZipEntry> srcEntries = zipSrc.entries();
+ while (srcEntries.hasMoreElements()) {
+ ZipEntry entry = srcEntries.nextElement();
+ ZipEntry newEntry = new ZipEntry(entry.getName());
+ newEntry.setTime(entry.getTime());
+ zos.putNextEntry(newEntry);
+ BufferedInputStream bis = new BufferedInputStream(zipSrc.getInputStream(entry));
+
+ if (entry.getName().endsWith(".class")) {
+ convert(bis, zos, params);
+ } else {
+ while (bis.available() > 0) {
+ zos.write(bis.read());
+ }
+ zos.closeEntry();
+ bis.close();
+ }
+ }
+ zos.finish();
+ }
+ }
+
+ private static void convert(InputStream in, OutputStream out,
+ TraceInjectionConfiguration params) throws IOException {
+ ClassReader cr = new ClassReader(in);
+ ClassWriter cw = new ClassWriter(0);
+ TraceInjectionClassVisitor cv = new TraceInjectionClassVisitor(cw, params);
+ cr.accept(cv, ClassReader.EXPAND_FRAMES);
+ byte[] data = cw.toByteArray();
+ out.write(data);
+ }
+}
diff --git a/tools/traceinjection/src/com/android/traceinjection/TraceInjectionClassVisitor.java b/tools/traceinjection/src/com/android/traceinjection/TraceInjectionClassVisitor.java
new file mode 100644
index 0000000..863f976
--- /dev/null
+++ b/tools/traceinjection/src/com/android/traceinjection/TraceInjectionClassVisitor.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.traceinjection;
+
+import org.objectweb.asm.ClassVisitor;
+import org.objectweb.asm.MethodVisitor;
+import org.objectweb.asm.Opcodes;
+
+/**
+ * {@link ClassVisitor} that injects tracing code to methods annotated with the configured
+ * annotation.
+ */
+public class TraceInjectionClassVisitor extends ClassVisitor {
+ private final TraceInjectionConfiguration mParams;
+ public TraceInjectionClassVisitor(ClassVisitor classVisitor,
+ TraceInjectionConfiguration params) {
+ super(Opcodes.ASM7, classVisitor);
+ mParams = params;
+ }
+
+ @Override
+ public MethodVisitor visitMethod(int access, String name, String desc, String signature,
+ String[] exceptions) {
+ MethodVisitor chain = super.visitMethod(access, name, desc, signature, exceptions);
+ return new TraceInjectionMethodAdapter(chain, access, name, desc, mParams);
+ }
+}
diff --git a/tools/traceinjection/src/com/android/traceinjection/TraceInjectionConfiguration.java b/tools/traceinjection/src/com/android/traceinjection/TraceInjectionConfiguration.java
new file mode 100644
index 0000000..f9595bd
--- /dev/null
+++ b/tools/traceinjection/src/com/android/traceinjection/TraceInjectionConfiguration.java
@@ -0,0 +1,52 @@
+/*
+ * 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.traceinjection;
+
+/**
+ * Configuration data for trace method injection.
+ */
+public class TraceInjectionConfiguration {
+ public final String annotation;
+ public final String startMethodClass;
+ public final String startMethodName;
+ public final String endMethodClass;
+ public final String endMethodName;
+
+ public TraceInjectionConfiguration(String annotation, String startMethod, String endMethod) {
+ this.annotation = annotation;
+ String[] startMethodComponents = parseMethod(startMethod);
+ String[] endMethodComponents = parseMethod(endMethod);
+ startMethodClass = startMethodComponents[0];
+ startMethodName = startMethodComponents[1];
+ endMethodClass = endMethodComponents[0];
+ endMethodName = endMethodComponents[1];
+ }
+
+ public String toString() {
+ return "TraceInjectionParams{annotation=" + annotation
+ + ", startMethod=" + startMethodClass + "." + startMethodName
+ + ", endMethod=" + endMethodClass + "." + endMethodName + "}";
+ }
+
+ private static String[] parseMethod(String method) {
+ String[] methodComponents = method.split("\\.");
+ if (methodComponents.length != 2) {
+ throw new IllegalArgumentException("Invalid method descriptor: " + method);
+ }
+ return methodComponents;
+ }
+}
diff --git a/tools/traceinjection/src/com/android/traceinjection/TraceInjectionMethodAdapter.java b/tools/traceinjection/src/com/android/traceinjection/TraceInjectionMethodAdapter.java
new file mode 100644
index 0000000..c2bbddc
--- /dev/null
+++ b/tools/traceinjection/src/com/android/traceinjection/TraceInjectionMethodAdapter.java
@@ -0,0 +1,183 @@
+/*
+ * 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.traceinjection;
+
+import org.objectweb.asm.AnnotationVisitor;
+import org.objectweb.asm.Label;
+import org.objectweb.asm.MethodVisitor;
+import org.objectweb.asm.Opcodes;
+import org.objectweb.asm.Type;
+import org.objectweb.asm.commons.AdviceAdapter;
+import org.objectweb.asm.commons.Method;
+
+/**
+ * Adapter that injects tracing code to methods annotated with the configured annotation.
+ *
+ * Assuming the configured annotation is {@code @Trace} and the configured methods are
+ * {@code Tracing.begin()} and {@code Tracing.end()}, it effectively transforms:
+ *
+ * <pre>{@code
+ * @Trace
+ * void method() {
+ * doStuff();
+ * }
+ * }</pre>
+ *
+ * into:
+ * <pre>{@code
+ * @Trace
+ * void method() {
+ * Tracing.begin();
+ * try {
+ * doStuff();
+ * } finally {
+ * Tracing.end();
+ * }
+ * }
+ * }</pre>
+ */
+public class TraceInjectionMethodAdapter extends AdviceAdapter {
+ private final TraceInjectionConfiguration mParams;
+ private final Label mStartFinally = newLabel();
+ private final boolean mIsConstructor;
+
+ private boolean mShouldTrace;
+ private long mTraceId;
+ private String mTraceLabel;
+
+ public TraceInjectionMethodAdapter(MethodVisitor methodVisitor, int access,
+ String name, String descriptor, TraceInjectionConfiguration params) {
+ super(Opcodes.ASM7, methodVisitor, access, name, descriptor);
+ mParams = params;
+ mIsConstructor = "<init>".equals(name);
+ }
+
+ @Override
+ public void visitCode() {
+ super.visitCode();
+ if (mShouldTrace) {
+ visitLabel(mStartFinally);
+ }
+ }
+
+ @Override
+ protected void onMethodEnter() {
+ if (!mShouldTrace) {
+ return;
+ }
+ Type type = Type.getType(toJavaSpecifier(mParams.startMethodClass));
+ Method trace = Method.getMethod("void " + mParams.startMethodName + " (long, String)");
+ push(mTraceId);
+ push(getTraceLabel());
+ invokeStatic(type, trace);
+ }
+
+ private String getTraceLabel() {
+ return !isEmpty(mTraceLabel) ? mTraceLabel : getName();
+ }
+
+ @Override
+ protected void onMethodExit(int opCode) {
+ // Any ATHROW exits will be caught as part of our exception-handling block, so putting it
+ // here would cause us to call the end trace method multiple times.
+ if (opCode != ATHROW) {
+ onFinally();
+ }
+ }
+
+ private void onFinally() {
+ if (!mShouldTrace) {
+ return;
+ }
+ Type type = Type.getType(toJavaSpecifier(mParams.endMethodClass));
+ Method trace = Method.getMethod("void " + mParams.endMethodName + " (long)");
+ push(mTraceId);
+ invokeStatic(type, trace);
+ }
+
+ @Override
+ public void visitMaxs(int maxStack, int maxLocals) {
+ final int minStackSize;
+ if (mShouldTrace) {
+ Label endFinally = newLabel();
+ visitLabel(endFinally);
+ catchException(mStartFinally, endFinally, null);
+ // The stack will always contain exactly one element: the exception we caught
+ final Object[] stack = new Object[]{ "java/lang/Throwable"};
+ // Because we use EXPAND_FRAMES, the frame type must always be F_NEW.
+ visitFrame(F_NEW, /* numLocal= */ 0, /* local= */ null, stack.length, stack);
+ onFinally();
+ // Rethrow the exception that we caught in the finally block.
+ throwException();
+
+ // Make sure we have at least enough stack space to push the trace arguments
+ // (long, String)
+ minStackSize = Type.LONG_TYPE.getSize() + Type.getType(String.class).getSize();
+ } else {
+ // We didn't inject anything, so no need for additional stack space.
+ minStackSize = 0;
+ }
+
+ super.visitMaxs(Math.max(minStackSize, maxStack), maxLocals);
+ }
+
+ @Override
+ public AnnotationVisitor visitAnnotation(String descriptor, boolean visible) {
+ AnnotationVisitor av = super.visitAnnotation(descriptor, visible);
+ if (descriptor.equals(toJavaSpecifier(mParams.annotation))) {
+ if (mIsConstructor) {
+ // TODO: Support constructor tracing. At the moment, constructors aren't supported
+ // because you can't put an exception handler around a super() call within the
+ // constructor itself.
+ throw new IllegalStateException("Cannot trace constructors");
+ }
+ av = new TracingAnnotationVisitor(av);
+ }
+ return av;
+ }
+
+ /**
+ * An AnnotationVisitor that pulls the trace ID and label information from the configured
+ * annotation.
+ */
+ class TracingAnnotationVisitor extends AnnotationVisitor {
+
+ TracingAnnotationVisitor(AnnotationVisitor annotationVisitor) {
+ super(Opcodes.ASM7, annotationVisitor);
+ }
+
+ @Override
+ public void visit(String name, Object value) {
+ if ("tag".equals(name)) {
+ mTraceId = (long) value;
+ // If we have a trace annotation and ID, then we have everything we need to trace
+ mShouldTrace = true;
+ } else if ("label".equals(name)) {
+ mTraceLabel = (String) value;
+ }
+ super.visit(name, value);
+ }
+ }
+
+ private static String toJavaSpecifier(String klass) {
+ return "L" + klass + ";";
+ }
+
+ private static boolean isEmpty(String str) {
+ return str == null || "".equals(str);
+ }
+}
diff --git a/tools/traceinjection/test/com/android/traceinjection/InjectionTests.java b/tools/traceinjection/test/com/android/traceinjection/InjectionTests.java
new file mode 100644
index 0000000..81bf235
--- /dev/null
+++ b/tools/traceinjection/test/com/android/traceinjection/InjectionTests.java
@@ -0,0 +1,246 @@
+/*
+ * 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.traceinjection;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertThrows;
+
+import org.junit.After;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+@RunWith(JUnit4.class)
+public class InjectionTests {
+ public static final int TRACE_TAG = 42;
+ public static final String CUSTOM_TRACE_NAME = "Custom";
+
+ public static final TraceTracker TRACKER = new TraceTracker();
+
+ @After
+ public void tearDown() {
+ TRACKER.reset();
+ }
+
+ @Test
+ public void testDefaultLabel() {
+ assertTraces(this::tracedMethod, "tracedMethod");
+ tracedMethodThrowsAndCatches();
+ }
+
+ @Test
+ public void testCustomLabel() {
+ assertTraces(this::tracedMethodHasCustomName, CUSTOM_TRACE_NAME);
+ }
+
+ @Test
+ public void testTracedMethodsStillThrow() {
+ assertTraces(() -> assertThrows(IllegalArgumentException.class, this::tracedMethodThrows),
+ "tracedMethodThrows");
+ // Also test that we rethrow exceptions from method calls. This is slightly different from
+ // the previous case because the ATHROW instruction is not actually present at all in the
+ // bytecode of the instrumented method.
+ TRACKER.reset();
+ assertTraces(() -> assertThrows(NullPointerException.class,
+ this::tracedMethodCallsThrowingMethod),
+ "tracedMethodCallsThrowingMethod");
+ }
+
+ @Test
+ public void testNestedTracedMethods() {
+ assertTraces(this::outerTracedMethod, "outerTracedMethod", "innerTracedMethod");
+ }
+
+ @Test
+ public void testTracedMethodWithCatchBlock() {
+ assertTraces(this::tracedMethodThrowsAndCatches, "tracedMethodThrowsAndCatches");
+ }
+
+ @Test
+ public void testTracedMethodWithFinallyBlock() {
+ assertTraces(() -> assertThrows(IllegalArgumentException.class,
+ this::tracedMethodThrowWithFinally), "tracedMethodThrowWithFinally");
+ }
+
+ @Test
+ public void testNonVoidMethod() {
+ assertTraces(this::tracedNonVoidMethod, "tracedNonVoidMethod");
+ }
+
+ @Test
+ public void testNonVoidMethodReturnsWithinCatches() {
+ assertTraces(this::tracedNonVoidMethodReturnsWithinCatches,
+ "tracedNonVoidMethodReturnsWithinCatches");
+ }
+
+ @Test
+ public void testNonVoidMethodReturnsWithinFinally() {
+ assertTraces(this::tracedNonVoidMethodReturnsWithinFinally,
+ "tracedNonVoidMethodReturnsWithinFinally");
+ }
+
+ @Test
+ public void testTracedStaticMethod() {
+ assertTraces(InjectionTests::tracedStaticMethod, "tracedStaticMethod");
+ }
+
+ @Trace(tag = TRACE_TAG)
+ public void tracedMethod() {
+ assertEquals(1, TRACKER.getTraceCount(TRACE_TAG));
+ }
+
+ @Trace(tag = TRACE_TAG)
+ public void tracedMethodThrows() {
+ throw new IllegalArgumentException();
+ }
+
+ @Trace(tag = TRACE_TAG)
+ public void tracedMethodCallsThrowingMethod() {
+ throwingMethod();
+ }
+
+ private void throwingMethod() {
+ throw new NullPointerException();
+ }
+
+
+ @Trace(tag = TRACE_TAG)
+ public void tracedMethodThrowsAndCatches() {
+ try {
+ throw new IllegalArgumentException();
+ } catch (IllegalArgumentException ignored) {
+ assertEquals(1, TRACKER.getTraceCount(TRACE_TAG));
+ }
+ }
+
+ @Trace(tag = TRACE_TAG)
+ public void tracedMethodThrowWithFinally() {
+ try {
+ throw new IllegalArgumentException();
+ } finally {
+ assertEquals(1, TRACKER.getTraceCount(TRACE_TAG));
+ }
+ }
+
+ @Trace(tag = TRACE_TAG, label = CUSTOM_TRACE_NAME)
+ public void tracedMethodHasCustomName() {
+ }
+
+ @Trace(tag = TRACE_TAG)
+ public void outerTracedMethod() {
+ innerTracedMethod();
+ assertEquals(1, TRACKER.getTraceCount(TRACE_TAG));
+ }
+
+ @Trace(tag = TRACE_TAG)
+ public void innerTracedMethod() {
+ assertEquals(2, TRACKER.getTraceCount(TRACE_TAG));
+ }
+
+ @Trace(tag = TRACE_TAG)
+ public int tracedNonVoidMethod() {
+ assertEquals(1, TRACKER.getTraceCount(TRACE_TAG));
+ return 0;
+ }
+
+ @Trace(tag = TRACE_TAG)
+ public int tracedNonVoidMethodReturnsWithinCatches() {
+ try {
+ throw new IllegalArgumentException();
+ } catch (IllegalArgumentException ignored) {
+ assertEquals(1, TRACKER.getTraceCount(TRACE_TAG));
+ return 0;
+ }
+ }
+
+ @Trace(tag = TRACE_TAG)
+ public int tracedNonVoidMethodReturnsWithinFinally() {
+ try {
+ throw new IllegalArgumentException();
+ } finally {
+ assertEquals(1, TRACKER.getTraceCount(TRACE_TAG));
+ return 0;
+ }
+ }
+
+ @Trace(tag = TRACE_TAG)
+ public static void tracedStaticMethod() {
+ assertEquals(1, TRACKER.getTraceCount(TRACE_TAG));
+ }
+
+ public void assertTraces(Runnable r, String... traceLabels) {
+ r.run();
+ assertEquals(Arrays.asList(traceLabels), TRACKER.getTraceLabels(TRACE_TAG));
+ TRACKER.assertAllTracesClosed();
+ }
+
+ public static void traceStart(long tag, String name) {
+ TRACKER.onTraceStart(tag, name);
+ }
+
+ public static void traceEnd(long tag) {
+ TRACKER.onTraceEnd(tag);
+ }
+
+ static class TraceTracker {
+ private final Map<Long, List<String>> mTraceLabelsByTag = new HashMap<>();
+ private final Map<Long, Integer> mTraceCountsByTag = new HashMap<>();
+
+ public void onTraceStart(long tag, String name) {
+ getTraceLabels(tag).add(name);
+ mTraceCountsByTag.put(tag, mTraceCountsByTag.getOrDefault(tag, 0) + 1);
+ }
+
+ public void onTraceEnd(long tag) {
+ final int newCount = getTraceCount(tag) - 1;
+ if (newCount < 0) {
+ throw new IllegalStateException("Trace count has gone negative for tag " + tag);
+ }
+ mTraceCountsByTag.put(tag, newCount);
+ }
+
+ public void reset() {
+ mTraceLabelsByTag.clear();
+ mTraceCountsByTag.clear();
+ }
+
+ public List<String> getTraceLabels(long tag) {
+ if (!mTraceLabelsByTag.containsKey(tag)) {
+ mTraceLabelsByTag.put(tag, new ArrayList<>());
+ }
+ return mTraceLabelsByTag.get(tag);
+ }
+
+ public int getTraceCount(long tag) {
+ return mTraceCountsByTag.getOrDefault(tag, 0);
+ }
+
+ public void assertAllTracesClosed() {
+ for (Map.Entry<Long, Integer> count: mTraceCountsByTag.entrySet()) {
+ final String errorMsg = "Tag " + count.getKey() + " is not fully closed (count="
+ + count.getValue() + ")";
+ assertEquals(errorMsg, 0, (int) count.getValue());
+ }
+ }
+ }
+}
diff --git a/media/java/android/media/tv/interactive/TvInteractiveAppInfo.aidl b/tools/traceinjection/test/com/android/traceinjection/Trace.java
similarity index 76%
copy from media/java/android/media/tv/interactive/TvInteractiveAppInfo.aidl
copy to tools/traceinjection/test/com/android/traceinjection/Trace.java
index 5e15016..9e1c545 100644
--- a/media/java/android/media/tv/interactive/TvInteractiveAppInfo.aidl
+++ b/tools/traceinjection/test/com/android/traceinjection/Trace.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2021 The Android Open Source Project
+ * Copyright (C) 2022 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -14,6 +14,9 @@
* limitations under the License.
*/
-package android.media.tv.interactive;
+package com.android.traceinjection;
-parcelable TvInteractiveAppInfo;
\ No newline at end of file
+public @interface Trace {
+ long tag();
+ String label() default "";
+}
diff --git a/tools/validatekeymaps/Android.bp b/tools/validatekeymaps/Android.bp
index 0423b7a..ff24d16 100644
--- a/tools/validatekeymaps/Android.bp
+++ b/tools/validatekeymaps/Android.bp
@@ -32,7 +32,7 @@
"libui-types",
],
target: {
- linux_glibc: {
+ host_linux: {
static_libs: [
// libbinder is only available for linux
"libbinder",