diff options
1096 files changed, 21781 insertions, 11106 deletions
diff --git a/Android.bp b/Android.bp index 753cefc38ed6..149b22355c58 100644 --- a/Android.bp +++ b/Android.bp @@ -97,6 +97,7 @@ filegroup { ":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 @@ java_defaults { "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 4ad015dcc4e5..c92c6340a6b4 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 static androidx.test.platform.app.InstrumentationRegistry.getInstrumentat 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 @@ public class RelayoutPerfTest extends WindowManagerPerfTestBase 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 e2426c2f1758..f822a188c99c 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 @@ package com.android.server.usage; 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 @@ public interface AppStandbyInternal { */ @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 90ec7000c6d1..528be3ca5e4b 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 @@ public class AlarmManagerService extends SystemService { 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 @@ public class AlarmManagerService extends SystemService { } } 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 @@ public class AlarmManagerService extends SystemService { 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 @@ public class AlarmManagerService extends SystemService { } } 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 18f63b7ad902..23056b5670b9 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.Context; 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 android.util.proto.ProtoOutputStream; 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 @@ class JobConcurrencyManager { 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 @@ class JobConcurrencyManager { 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 @@ class JobConcurrencyManager { case PowerManager.ACTION_DEVICE_IDLE_MODE_CHANGED: if (mPowerManager != null && mPowerManager.isDeviceIdleMode()) { synchronized (mLock) { + stopUnexemptedJobsForDoze(); stopLongRunningJobsLocked("deep doze"); } } @@ -471,6 +499,11 @@ class JobConcurrencyManager { } @GuardedBy("mLock") + ArraySet<JobStatus> getRunningJobsLocked() { + return mRunningJobs; + } + + @GuardedBy("mLock") boolean isJobRunningLocked(JobStatus job) { return mRunningJobs.contains(job); } @@ -546,7 +579,7 @@ class JobConcurrencyManager { } 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 @@ class JobConcurrencyManager { } @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 @@ class JobConcurrencyManager { } } + @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 @@ class JobConcurrencyManager { } @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 @@ class JobConcurrencyManager { } } + @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 b9362789c6c6..3d74bc98ad32 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.content.pm.ServiceInfo; 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.Message; 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 android.util.proto.ProtoOutputStream; 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.AppStateTrackerImpl; 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 @@ public class JobSchedulerService extends com.android.server.SystemService 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 @@ public class JobSchedulerService extends com.android.server.SystemService PackageManagerInternal mLocalPM; ActivityManagerInternal mActivityManagerInternal; - IBatteryStats mBatteryStats; DeviceIdleInternal mLocalDeviceIdleController; @VisibleForTesting AppStateTrackerImpl mAppStateTracker; @@ -1578,7 +1567,8 @@ public class JobSchedulerService extends com.android.server.SystemService 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 @@ public class JobSchedulerService extends com.android.server.SystemService 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 @@ public class JobSchedulerService extends com.android.server.SystemService // 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 @@ public class JobSchedulerService extends com.android.server.SystemService 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 @@ public class JobSchedulerService extends com.android.server.SystemService 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 @@ public class JobSchedulerService extends com.android.server.SystemService * - 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 @@ public class JobSchedulerService extends com.android.server.SystemService 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 @@ public class JobSchedulerService extends com.android.server.SystemService 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 @@ public class JobSchedulerService extends com.android.server.SystemService 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 @@ public class JobSchedulerService extends com.android.server.SystemService } 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 @@ public class JobSchedulerService extends com.android.server.SystemService 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 @@ public class JobSchedulerService extends com.android.server.SystemService 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 efcf14f07ee9..30fdb1e9ad4e 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 @@ public final class JobStatus { /** 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 67a3dc67e569..5ec2f5607153 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 @@ class ProcessStateModifier extends Modifier { 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 dd102bdd726e..2e3b377d08a5 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 @@ public class AppIdleHistory { 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 @@ public class AppIdleHistory { 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 @@ public class AppIdleHistory { // 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 @@ public class AppIdleHistory { 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 @@ public class AppIdleHistory { + " 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 @@ public class AppIdleHistory { 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 4952894c068b..502913063a00 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.os.UserHandle; 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.ArrayList; 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 @@ public class AppStandbyController 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 @@ public class AppStandbyController } } + 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 @@ public class AppStandbyController } @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 @@ public class AppStandbyController } 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 c5410a082322..b8d24e388d67 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 @@ public class Am extends BaseCommand { 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 a0562d964954..7ff4bc4bcf76 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_ALWAYS_CHECK_SIGNATURE; 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 @@ public class Instrument { // Required public String componentNameArg; public boolean alwaysCheckSignature = false; + public boolean instrumentSdkSandbox = false; /** * Construct the instrument command runner. @@ -524,6 +526,9 @@ public class Instrument { 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 6a685a79cc33..a1575173ded6 100644 --- a/cmds/app_process/Android.bp +++ b/cmds/app_process/Android.bp @@ -64,8 +64,6 @@ cc_binary { "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 815f9455471c..12083b6fe20b 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 @@ int main(int argc, char* const argv[]) 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 c202f6f03b5b..6ef6845c75f2 100644 --- a/cmds/idmap2/Android.bp +++ b/cmds/idmap2/Android.bp @@ -52,6 +52,7 @@ cc_defaults { "-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 19ffd36eb47a..37022d0ab402 100644 --- a/core/api/current.txt +++ b/core/api/current.txt @@ -854,7 +854,6 @@ package android { 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 @@ package android.animation { 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 @@ package android.animation { } public static interface ValueAnimator.DurationScaleChangeListener { - method public void onChanged(float); + method public void onChanged(@FloatRange(from=0) float); } } @@ -4532,22 +4531,36 @@ package android.app { } 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 @@ package android.app { 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 @@ package android.app { 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 @@ package android.app { 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 @@ package android.app.admin { 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 @@ package android.app.admin { 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 @@ package android.app.admin { 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 @@ package android.app.admin { } 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 @@ package android.content { 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 @@ package android.content { 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 @@ package android.content { 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 @@ package android.content { 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 @@ package android.content.pm { 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 @@ package android.content.pm { 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 @@ package android.content.pm { 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 @@ package android.content.pm { 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 @@ package android.content.pm { 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.pdf { 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 @@ package android.graphics.text { 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 @@ package android.hardware.camera2 { 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 @@ package android.hardware.camera2.params { 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 @@ package android.hardware.camera2.params { 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 @@ package android.hardware.camera2.params { 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 @@ package android.location { 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 @@ package android.location { 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 @@ package android.media { 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 @@ package android.media { 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 @@ package android.media { 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 @@ package android.media { 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 @@ package android.media { 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 @@ package android.media { 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 @@ package android.media { } 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 @@ package android.media.tv { } 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 @@ package android.media.tv { 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 @@ package android.media.tv { 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 @@ package android.media.tv { 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 { 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 @@ package android.media.tv.interactive { 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 @@ package android.media.tv.interactive { 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 @@ package android.media.tv.interactive { 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 @@ package android.media.tv.interactive { 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 @@ package android.media.tv.interactive { 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 @@ package android.media.tv.interactive { 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 @@ package android.media.tv.interactive { 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 @@ package android.media.tv.interactive { 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 @@ package android.media.tv.interactive { 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 @@ package android.media.tv.interactive { 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 @@ package android.net { 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 @@ package android.net { 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 @@ package android.net { 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 { @@ -38133,6 +38201,7 @@ package android.service.autofill { method public int getNoSaveUiReason(); method @NonNull public java.util.Set<java.lang.String> getSelectedDatasetIds(); method public int getType(); + method public int getUiType(); field public static final int NO_SAVE_UI_REASON_DATASET_MATCH = 6; // 0x6 field public static final int NO_SAVE_UI_REASON_FIELD_VALIDATION_FAILED = 5; // 0x5 field public static final int NO_SAVE_UI_REASON_HAS_EMPTY_REQUIRED = 3; // 0x3 @@ -38146,6 +38215,10 @@ package android.service.autofill { field public static final int TYPE_DATASET_AUTHENTICATION_SELECTED = 1; // 0x1 field public static final int TYPE_DATASET_SELECTED = 0; // 0x0 field public static final int TYPE_SAVE_SHOWN = 3; // 0x3 + field public static final int UI_TYPE_DIALOG = 3; // 0x3 + field public static final int UI_TYPE_INLINE = 2; // 0x2 + field public static final int UI_TYPE_MENU = 1; // 0x1 + field public static final int UI_TYPE_UNKNOWN = 0; // 0x0 } public final class FillRequest implements android.os.Parcelable { @@ -38160,6 +38233,7 @@ package android.service.autofill { 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 +43856,7 @@ package android.telephony.data { 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 +43864,7 @@ package android.telephony.data { 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 +45138,7 @@ package android.text { 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 +49352,7 @@ package android.view { 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); @@ -54052,9 +54129,13 @@ package android.view.translation { public interface UiTranslationStateCallback { method public void onFinished(); + method public default void onFinished(@NonNull String); method public void onPaused(); + method public default void onPaused(@NonNull String); method public default void onResumed(@NonNull android.icu.util.ULocale, @NonNull android.icu.util.ULocale); + method public default void onResumed(@NonNull android.icu.util.ULocale, @NonNull android.icu.util.ULocale, @NonNull String); method public default void onStarted(@NonNull android.icu.util.ULocale, @NonNull android.icu.util.ULocale); + method public default void onStarted(@NonNull android.icu.util.ULocale, @NonNull android.icu.util.ULocale, @NonNull String); } @UiThread public interface ViewTranslationCallback { @@ -57352,7 +57433,8 @@ package android.widget { 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 +57562,8 @@ package android.widget { 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 +57973,7 @@ package android.window { } 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 3d5232ba4f35..44a79c61e216 100644 --- a/core/api/module-lib-current.txt +++ b/core/api/module-lib-current.txt @@ -4,6 +4,7 @@ package android { public static final class Manifest.permission { field public static final String CONTROL_AUTOMOTIVE_GNSS = "android.permission.CONTROL_AUTOMOTIVE_GNSS"; field public static final String GET_INTENT_SENDER_INTENT = "android.permission.GET_INTENT_SENDER_INTENT"; + field public static final String MAKE_UID_VISIBLE = "android.permission.MAKE_UID_VISIBLE"; } } @@ -102,7 +103,7 @@ package android.content.pm { public abstract class PackageManager { method @NonNull public String getPermissionControllerPackageName(); method @NonNull public String getSdkSandboxPackageName(); - method @RequiresPermission("android.permission.MAKE_UID_VISIBLE") public void makeUidVisible(int, int); + method @RequiresPermission(android.Manifest.permission.MAKE_UID_VISIBLE) public void makeUidVisible(int, int); field public static final String EXTRA_VERIFICATION_ROOT_HASH = "android.content.pm.extra.VERIFICATION_ROOT_HASH"; field public static final int MATCH_STATIC_SHARED_AND_SDK_LIBRARIES = 67108864; // 0x4000000 } @@ -243,7 +244,8 @@ package android.net { 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 09d111418e06..0a748142d65e 100644 --- a/core/api/system-current.txt +++ b/core/api/system-current.txt @@ -5,6 +5,7 @@ package android { 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 @@ package android { 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 @@ package android.app.admin { 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(); @@ -1087,10 +1090,9 @@ package android.app.admin { method @Nullable @RequiresPermission(android.Manifest.permission.MANAGE_USERS) public android.os.UserHandle getDeviceOwnerUser(); method @Nullable @RequiresPermission(anyOf={android.Manifest.permission.MANAGE_USERS, android.Manifest.permission.QUERY_ADMIN_POLICY}) public java.util.List<java.lang.String> getPermittedAccessibilityServices(int); method @Nullable @RequiresPermission(anyOf={android.Manifest.permission.MANAGE_USERS, android.Manifest.permission.QUERY_ADMIN_POLICY}) public java.util.List<java.lang.String> getPermittedInputMethodsForCurrentUser(); + method @NonNull @RequiresPermission(android.Manifest.permission.MANAGE_PROFILE_AND_DEVICE_OWNERS) public java.util.List<android.os.UserHandle> getPolicyManagedProfiles(@NonNull android.os.UserHandle); 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 +1105,14 @@ package android.app.admin { 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 +1127,7 @@ package android.app.admin { 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 +1147,7 @@ package android.app.admin { 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 +1161,9 @@ package android.app.admin { 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 +1190,6 @@ package android.app.admin { } 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 +1201,13 @@ package android.app.admin { 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 +1896,7 @@ package android.app.prediction { 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 +2592,13 @@ package android.app.usage { } 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 +3164,7 @@ package android.content.pm { } 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 +3384,8 @@ package android.content.pm { 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 +5463,32 @@ package android.location { 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 +5570,18 @@ package android.location { 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 +5590,18 @@ package android.location { 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 +5843,9 @@ package android.location { 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 +5874,7 @@ package android.location { 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 +5907,7 @@ package android.location { 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 +5923,9 @@ package android.location { } 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 +9798,7 @@ package android.os { 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 +9816,10 @@ package android.os { 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 +10054,9 @@ package android.permission { 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 +10870,11 @@ package android.service.ambientcontext { } 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 +10895,8 @@ package android.service.ambientcontext { } 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 +11378,7 @@ package android.service.games { 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 66f893d71ef9..a67d002cdddf 100644 --- a/core/api/test-current.txt +++ b/core/api/test-current.txt @@ -96,7 +96,7 @@ package android.accessibilityservice { 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 @@ package android.app { } public class LocaleManager { - method @Nullable public android.os.LocaleList getSystemLocales(); method public void setSystemLocales(@NonNull android.os.LocaleList); } @@ -356,14 +355,8 @@ package android.app { } 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 @@ package android.app.admin { 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 @@ package android.app.admin { 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 @@ package android.app.admin { 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.quicksettings { 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 a5526bc66431..f081a439c49c 100644 --- a/core/java/Android.bp +++ b/core/java/Android.bp @@ -145,16 +145,16 @@ genrule { 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 4e6cfb358901..f53cfe457b64 100644 --- a/core/java/android/accessibilityservice/AccessibilityShortcutInfo.java +++ b/core/java/android/accessibilityservice/AccessibilityShortcutInfo.java @@ -169,10 +169,6 @@ public final class AccessibilityShortcutInfo { 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 36cfd0e4341e..c0e5e84d369a 100644 --- a/core/java/android/accessibilityservice/InputMethod.java +++ b/core/java/android/accessibilityservice/InputMethod.java @@ -67,6 +67,10 @@ public class InputMethod { 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 107efc3cce95..3fac1a0bdea0 100644 --- a/core/java/android/accounts/CantAddAccountActivity.java +++ b/core/java/android/accounts/CantAddAccountActivity.java @@ -39,7 +39,7 @@ public class CantAddAccountActivity extends Activity { 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 0d82ac942148..f623295dee3e 100644 --- a/core/java/android/accounts/ChooseTypeAndAccountActivity.java +++ b/core/java/android/accounts/ChooseTypeAndAccountActivity.java @@ -205,7 +205,7 @@ public class ChooseTypeAndAccountActivity extends Activity 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 bca6b6a0ddd0..6ab7ae6d0cee 100644 --- a/core/java/android/animation/ValueAnimator.java +++ b/core/java/android/animation/ValueAnimator.java @@ -316,7 +316,7 @@ public class ValueAnimator extends Animator implements AnimationHandler.Animatio @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 @@ public class ValueAnimator extends Animator implements AnimationHandler.Animatio * * @return the duration scale. */ - @FloatRange(from = 0, to = 1) + @FloatRange(from = 0) public static float getDurationScale() { return sDurationScale; } @@ -1798,8 +1798,8 @@ public class ValueAnimator extends Animator implements AnimationHandler.Animatio 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/Activity.java b/core/java/android/app/Activity.java index ec9bb264835e..a28b3e9fc545 100644 --- a/core/java/android/app/Activity.java +++ b/core/java/android/app/Activity.java @@ -872,7 +872,7 @@ public class Activity extends ContextThemeWrapper @UnsupportedAppUsage /*package*/ int mConfigChangeFlags; @UnsupportedAppUsage - /*package*/ Configuration mCurrentConfig; + /*package*/ Configuration mCurrentConfig = Configuration.EMPTY; private SearchManager mSearchManager; private MenuInflater mMenuInflater; diff --git a/core/java/android/app/ActivityManager.java b/core/java/android/app/ActivityManager.java index 9f1510526bae..e8c903fc2f13 100644 --- a/core/java/android/app/ActivityManager.java +++ b/core/java/android/app/ActivityManager.java @@ -22,6 +22,7 @@ import static android.content.Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS; 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 @@ public class ActivityManager { * @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 @@ public class ActivityManager { 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 @@ public class ActivityManager { * 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 @@ public class ActivityManager { * @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 @@ public class ActivityManager { * 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 @@ public class ActivityManager { * @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 @@ public class ActivityManager { * * @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 @@ public class ActivityManager { /** * @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 @@ public class ActivityManager { } /** - * @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/ActivityThread.java b/core/java/android/app/ActivityThread.java index 3d0ed20b60c6..3b843a9c622a 100644 --- a/core/java/android/app/ActivityThread.java +++ b/core/java/android/app/ActivityThread.java @@ -5885,19 +5885,17 @@ public final class ActivityThread extends ClientTransactionHandler final boolean movedToDifferentDisplay = isDifferentDisplay(activity.getDisplayId(), displayId); final Configuration currentConfig = activity.mCurrentConfig; - final int diff = (currentConfig == null) ? 0xffffffff - : currentConfig.diffPublicOnly(newConfig); + final int diff = currentConfig.diffPublicOnly(newConfig); final boolean hasPublicConfigChange = diff != 0; + final ActivityClientRecord r = getActivityClient(activityToken); // TODO(b/173090263): Use diff instead after the improvement of AssetManager and // ResourcesImpl constructions. final boolean shouldUpdateResources = hasPublicConfigChange || shouldUpdateResources(activityToken, currentConfig, newConfig, amOverrideConfig, movedToDifferentDisplay, hasPublicConfigChange); - final boolean shouldReportChange = hasPublicConfigChange - // If this activity doesn't handle any of the config changes, then don't bother - // calling onConfigurationChanged. Otherwise, report to the activity for the - // changes. - && (~activity.mActivityInfo.getRealConfigChanged() & diff) == 0; + final boolean shouldReportChange = shouldReportChange(diff, currentConfig, newConfig, + r != null ? r.mSizeConfigurations : null, + activity.mActivityInfo.getRealConfigChanged()); // Nothing significant, don't proceed with updating and reporting. if (!shouldUpdateResources) { return null; @@ -5944,6 +5942,40 @@ public final class ActivityThread extends ClientTransactionHandler return configToReport; } + /** + * Returns {@code true} if {@link Activity#onConfigurationChanged(Configuration)} should be + * dispatched. + * + * @param publicDiff Usually computed by {@link Configuration#diffPublicOnly(Configuration)}. + * This parameter is to prevent we compute it again. + * @param currentConfig The current configuration cached in {@link Activity#mCurrentConfig}. + * It is {@code null} before the first config update from the server side. + * @param newConfig The updated {@link Configuration} + * @param sizeBuckets The Activity's {@link SizeConfigurationBuckets} if not {@code null} + * @param handledConfigChanges Bit mask of configuration changes that the activity can handle + * @return {@code true} if the config change should be reported to the Activity + */ + @VisibleForTesting + public static boolean shouldReportChange(int publicDiff, @Nullable Configuration currentConfig, + @NonNull Configuration newConfig, @Nullable SizeConfigurationBuckets sizeBuckets, + int handledConfigChanges) { + // Don't report the change if there's no public diff between current and new config. + if (publicDiff == 0) { + return false; + } + final int diffWithBucket = SizeConfigurationBuckets.filterDiff(publicDiff, currentConfig, + newConfig, sizeBuckets); + // Compare to the diff which filter the change without crossing size buckets with + // {@code handledConfigChanges}. The small changes should not block Activity to receive + // its handled config updates. Also, if Activity handles all small changes, we should + // dispatch the updated config to it. + final int diff = diffWithBucket != 0 ? diffWithBucket : publicDiff; + // If this activity doesn't handle any of the config changes, then don't bother + // calling onConfigurationChanged. Otherwise, report to the activity for the + // changes. + return (~handledConfigChanges & diff) == 0; + } + public final void applyConfigurationToResources(Configuration config) { synchronized (mResourcesManager) { mResourcesManager.applyConfigurationToResources(config, null); diff --git a/core/java/android/app/ApplicationPackageManager.java b/core/java/android/app/ApplicationPackageManager.java index 7ffa61be7604..d641a3b469a6 100644 --- a/core/java/android/app/ApplicationPackageManager.java +++ b/core/java/android/app/ApplicationPackageManager.java @@ -18,9 +18,9 @@ package android.app; 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 @@ public class ApplicationPackageManager extends PackageManager { return icon; } - final Drawable badgeForeground = getDevicePolicyManager().getDrawable( + final Drawable badgeForeground = getDevicePolicyManager().getResources().getDrawable( getUpdatableUserIconBadgeId(user), SOLID_COLORED, () -> getDefaultUserIconBadge(user)); @@ -1938,11 +1938,12 @@ public class ApplicationPackageManager extends PackageManager { 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 @@ public class ApplicationPackageManager extends PackageManager { 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 f5eb1f6e24ed..ac46066997ff 100644 --- a/core/java/android/app/ContextImpl.java +++ b/core/java/android/app/ContextImpl.java @@ -77,6 +77,7 @@ import android.os.Trace; 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 @@ class ContextImpl extends Context { @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 @@ class ContextImpl extends Context { } @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 82ff42b41799..a763b1464b6d 100644 --- a/core/java/android/app/Dialog.java +++ b/core/java/android/app/Dialog.java @@ -465,7 +465,8 @@ public class Dialog implements DialogInterface, Window.Callback, 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 6f49c9e647a4..a138fa1f6fd5 100644 --- a/core/java/android/app/GameManager.java +++ b/core/java/android/app/GameManager.java @@ -191,7 +191,7 @@ public final class GameManager { */ @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 348cb2d30739..3002c8bb9c3e 100644 --- a/core/java/android/app/ILocaleManager.aidl +++ b/core/java/android/app/ILocaleManager.aidl @@ -40,4 +40,9 @@ import android.os.LocaleList; */ 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 e0c69df0aa18..ac979c495cf3 100644 --- a/core/java/android/app/Instrumentation.java +++ b/core/java/android/app/Instrumentation.java @@ -393,6 +393,15 @@ public class Instrumentation { } /** + * 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 cedf483eb076..e9c29b8aa0a5 100644 --- a/core/java/android/app/KeyguardManager.java +++ b/core/java/android/app/KeyguardManager.java @@ -1103,9 +1103,12 @@ public class KeyguardManager { } /** - * 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 @@ public class KeyguardManager { } /** - * 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 522dc845f57c..efe9e35d4c64 100644 --- a/core/java/android/app/LocaleManager.java +++ b/core/java/android/app/LocaleManager.java @@ -18,7 +18,6 @@ package android.app; import android.Manifest; import android.annotation.NonNull; -import android.annotation.Nullable; import android.annotation.RequiresPermission; import android.annotation.SystemApi; import android.annotation.SystemService; @@ -127,31 +126,36 @@ public class LocaleManager { } /** - * Sets the current system locales to the provided value. + * Returns the current system locales, ignoring app-specific overrides. * - * @hide + * <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. */ - @TestApi - public void setSystemLocales(@NonNull LocaleList locales) { + @NonNull + public LocaleList getSystemLocales() { try { - Configuration conf = ActivityManager.getService().getConfiguration(); - conf.setLocales(locales); - ActivityManager.getService().updatePersistentConfiguration(conf); + return mService.getSystemLocales(); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } } /** - * Returns the current system locales for the device. + * Sets the current system locales to the provided value. * * @hide */ @TestApi - @Nullable - public LocaleList getSystemLocales() { + public void setSystemLocales(@NonNull LocaleList locales) { try { - return ActivityManager.getService().getConfiguration().getLocales(); + Configuration conf = ActivityManager.getService().getConfiguration(); + conf.setLocales(locales); + ActivityManager.getService().updatePersistentConfiguration(conf); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } diff --git a/core/java/android/app/Notification.java b/core/java/android/app/Notification.java index 7e0cea8921a4..6e1d1cd2e4c9 100644 --- a/core/java/android/app/Notification.java +++ b/core/java/android/app/Notification.java @@ -19,8 +19,8 @@ package android.app; 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 @@ public class Notification implements Parcelable // 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 2d2788ca91a3..3f1844e2ba8a 100644 --- a/core/java/android/app/PictureInPictureParams.java +++ b/core/java/android/app/PictureInPictureParams.java @@ -280,7 +280,7 @@ public final class PictureInPictureParams implements Parcelable { 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 @@ public final class PictureInPictureParams implements Parcelable { * @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 @@ public final class PictureInPictureParams implements Parcelable { * @hide */ @TestApi - public float getExpandedAspectRatio() { + public float getExpandedAspectRatioFloat() { if (mExpandedAspectRatio != null) { return mExpandedAspectRatio.floatValue(); } @@ -474,6 +480,17 @@ public final class PictureInPictureParams implements Parcelable { } /** + * 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 @@ public final class PictureInPictureParams implements Parcelable { } /** - * @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 @@ public final class PictureInPictureParams implements Parcelable { } /** - * @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 @@ public final class PictureInPictureParams implements Parcelable { } /** - * @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 @@ public final class PictureInPictureParams implements Parcelable { } /** - * @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 @@ public final class PictureInPictureParams implements Parcelable { } /** - * @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 @@ public final class PictureInPictureParams implements Parcelable { } /** - * @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 @@ public final class PictureInPictureParams implements Parcelable { @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 89854bbab3e8..ae0fc09e35a6 100644 --- a/core/java/android/app/StatusBarManager.java +++ b/core/java/android/app/StatusBarManager.java @@ -24,6 +24,9 @@ import android.annotation.RequiresPermission; 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.Bundle; 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 @@ public class StatusBarManager { 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 @@ public class StatusBarManager { } } + /** + * 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 bf6f63414574..6615374f71ec 100644 --- a/core/java/android/app/SystemServiceRegistry.java +++ b/core/java/android/app/SystemServiceRegistry.java @@ -154,6 +154,7 @@ import android.net.vcn.VcnManager; 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 @@ public final class SystemServiceRegistry { 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 32207af22dc1..649f90442536 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 7fd8e896bac2..dab98884ff82 100644 --- a/core/java/android/app/admin/DevicePolicyDrawableResource.java +++ b/core/java/android/app/admin/DevicePolicyDrawableResource.java @@ -20,7 +20,6 @@ import android.annotation.DrawableRes; 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 @@ import java.util.Objects; /** * 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 final class DevicePolicyDrawableResource implements Parcelable { */ 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 @@ public final class DevicePolicyDrawableResource implements Parcelable { } 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 @@ public final class DevicePolicyDrawableResource implements Parcelable { /** * 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 final class DevicePolicyDrawableResource implements Parcelable { */ 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 @@ public final class DevicePolicyDrawableResource implements Parcelable { * Returns the ID of the drawable to update. */ @NonNull - @DevicePolicyResources.UpdatableDrawableId public String getDrawableId() { return mDrawableId; } @@ -125,7 +123,6 @@ public final class DevicePolicyDrawableResource implements Parcelable { * Returns the style of the drawable to update */ @NonNull - @DevicePolicyResources.UpdatableDrawableStyle public String getDrawableStyle() { return mDrawableStyle; } @@ -134,7 +131,6 @@ public final class DevicePolicyDrawableResource implements Parcelable { * 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 4c7b91056ca1..487674066815 100644 --- a/core/java/android/app/admin/DevicePolicyManager.java +++ b/core/java/android/app/admin/DevicePolicyManager.java @@ -21,6 +21,7 @@ import static android.net.NetworkCapabilities.NET_ENTERPRISE_ID_1; 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.annotation.WorkerThread; 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; 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.telephony.data.ApnSetting; 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.CompletableFuture; 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 @@ public class DevicePolicyManager { 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 @@ public class DevicePolicyManager { mContext = context; mService = service; mParentInstance = parentInstance; + mResourcesManager = new DevicePolicyResourcesManager(context, service); } /** @hide test will override it. */ @@ -719,10 +717,11 @@ public class DevicePolicyManager { /** * 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 @@ public class DevicePolicyManager { "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 @@ public class DevicePolicyManager { * * <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_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_POLICY_MANAGEMENT_ROLE_HOLDER_RECOVERABLE_ERROR = + 1; + + /** + * 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_POLICY_MANAGEMENT_ROLE_HOLDER_UNRECOVERABLE_ERROR = + 2; /** - * 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 role holder provisioning + * is disabled. * * @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_PROVISIONING_DISABLED = 3; /** - * 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. + * 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 int RESULT_UPDATE_DEVICE_MANAGEMENT_ROLE_HOLDER_UNRECOVERABLE_ERROR = 2; + 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 @@ public class DevicePolicyManager { * <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 @@ public class DevicePolicyManager { /** * 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 @@ public class DevicePolicyManager { /** * 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 @@ public class DevicePolicyManager { "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 @@ public class DevicePolicyManager { @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 @@ public class DevicePolicyManager { } /** + * 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,376 +15293,53 @@ public class DevicePolicyManager { } /** - * 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 - */ - @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. + * Returns a {@link DevicePolicyResourcesManager} containing the required APIs to set, reset, + * and get device policy related resources. */ - @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); + @NonNull + public DevicePolicyResourcesManager getResources() { + return mResourcesManager; } - /** - * 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> + * Returns a boolean for whether the DPC + * (Device Policy Controller, the agent responsible for enforcing policy) + * has been downloaded during provisioning. * - * @param strings The list of {@link DevicePolicyStringResource} to update. + * <p>If true is returned, then any attempts to begin setup again should result in factory reset * * @hide */ @SystemApi - @RequiresPermission(android.Manifest.permission.UPDATE_DEVICE_MANAGEMENT_RESOURCES) - public void setStrings(@NonNull Set<DevicePolicyStringResource> strings) { + @RequiresPermission(android.Manifest.permission.MANAGE_PROFILE_AND_DEVICE_OWNERS) + public boolean isDpcDownloaded() { + throwIfParentInstance("isDpcDownloaded"); if (mService != null) { try { - mService.setStrings(new ArrayList<>(strings)); + return mService.isDpcDownloaded(); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } } + return false; } /** - * 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. + * Indicates that the DPC (Device Policy Controller, the agent responsible for enforcing policy) + * has or has not been downloaded during provisioning. * - * @param stringIds The list of IDs to remove the updated resources for. + * @param downloaded {@code true} if the dpc has been downloaded during provisioning. + * {@code false} otherwise. * * @hide */ @SystemApi - @RequiresPermission(android.Manifest.permission.UPDATE_DEVICE_MANAGEMENT_RESOURCES) - public void resetStrings(@NonNull String[] stringIds) { + @RequiresPermission(android.Manifest.permission.MANAGE_PROFILE_AND_DEVICE_OWNERS) + public void setDpcDownloaded(boolean downloaded) { + throwIfParentInstance("setDpcDownloaded"); if (mService != null) { try { - mService.resetStrings(stringIds); + mService.setDpcDownloaded(downloaded); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } @@ -15579,162 +15347,58 @@ public class DevicePolicyManager { } /** - * 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}. + * Returns the package name of the device policy management role holder. * - * @hide + * <p>If the device policy management role holder is not configured for this device, returns + * {@code null}. */ - @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); + public String getDevicePolicyManagementRoleHolderPackage() { + String devicePolicyManagementConfig = mContext.getString( + com.android.internal.R.string.config_devicePolicyManagement); + return extractPackageNameFromDeviceManagerConfig(devicePolicyManagementConfig); } /** - * 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...)}). + * Returns the package name of the device policy management role holder updater. * - * <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. + * <p>If the device policy management role holder updater is not configured for this device, + * returns {@code null}. * * @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); - } - - /** - * Returns a boolean for whether the DPC - * (Device Policy Controller, the agent responsible for enforcing policy) - * has been downloaded during provisioning. - * - * <p>If true is returned, then any attempts to begin setup again should result in factory reset - * - * @hide - */ - @SystemApi - @RequiresPermission(android.Manifest.permission.MANAGE_PROFILE_AND_DEVICE_OWNERS) - public boolean isDpcDownloaded() { - throwIfParentInstance("isDpcDownloaded"); - if (mService != null) { - try { - return mService.isDpcDownloaded(); - } catch (RemoteException e) { - throw e.rethrowFromSystemServer(); - } + @TestApi + public String getDevicePolicyManagementRoleHolderUpdaterPackage() { + String devicePolicyManagementUpdaterConfig = mContext.getString( + com.android.internal.R.string.config_devicePolicyManagementUpdater); + if (TextUtils.isEmpty(devicePolicyManagementUpdaterConfig)) { + return null; } - return false; + return devicePolicyManagementUpdaterConfig; } /** - * Indicates that the DPC (Device Policy Controller, the agent responsible for enforcing policy) - * has or has not been downloaded during provisioning. + * Returns a {@link List} of managed profiles managed by some profile owner within the profile + * group of the given user, or an empty {@link List} if there is not one. * - * @param downloaded {@code true} if the dpc has been downloaded during provisioning. - * {@code false} otherwise. + * @param user the user whose profile group to look within to return managed profiles * * @hide */ @SystemApi - @RequiresPermission(android.Manifest.permission.MANAGE_PROFILE_AND_DEVICE_OWNERS) - public void setDpcDownloaded(boolean downloaded) { - throwIfParentInstance("setDpcDownloaded"); + @RequiresPermission(permission.MANAGE_PROFILE_AND_DEVICE_OWNERS) + @NonNull + public List<UserHandle> getPolicyManagedProfiles(@NonNull UserHandle user) { + Objects.requireNonNull(user); if (mService != null) { try { - mService.setDpcDownloaded(downloaded); + return mService.getPolicyManagedProfiles(user); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } } - } - - /** - * Returns the package name of the device policy management role holder. - * - * <p>If the device policy management role holder is not configured for this device, returns - * {@code null}. - */ - @Nullable - public String getDevicePolicyManagementRoleHolderPackage() { - String deviceManagerConfig = mContext.getString( - com.android.internal.R.string.config_devicePolicyManagement); - return extractPackageNameFromDeviceManagerConfig(deviceManagerConfig); + return Collections.emptyList(); } /** @@ -15760,4 +15424,23 @@ public class DevicePolicyManager { } 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 042e407becb4..2b3780e5a32b 100644 --- a/core/java/android/app/admin/DevicePolicyResources.java +++ b/core/java/android/app/admin/DevicePolicyResources.java @@ -16,531 +16,39 @@ 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 - */ - @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 + * An identifier used for: + * <ul> + * <li>un-updatable resource IDs</li> + * <li>undefined sources</li> + * </ul> */ - @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 { - } + public static final String UNDEFINED = "UNDEFINED"; /** - * Resource identifiers used to update device management-related string resources. + * Class containing the identifiers used to update device management-related system drawable. * * @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 { - } - - /** - * Class containing the identifiers used to update device management-related system drawable. - */ public static final class Drawables { private Drawables() { } /** - * 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 final class DevicePolicyResources { 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 @@ public final class DevicePolicyResources { } /** - * 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 @@ public final class DevicePolicyResources { * 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 @@ public final class DevicePolicyResources { * 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 @@ public final class DevicePolicyResources { } /** - * 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 @@ public final class DevicePolicyResources { * 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 @@ public final class DevicePolicyResources { * 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 final class DevicePolicyResources { */ 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. - */ - public static final class DocumentsUi { - - private DocumentsUi() { - } - - private static final String PREFIX = "DocumentsUi."; - - /** - * Title for error message shown when work profile is turned off. - */ - 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; - } } /** * Class containing the identifiers used to update device management-related system strings - * in the MediaProvider module. + * in the Dialer app. + * + * @hide */ - public static final class MediaProvider { + public static final class Telecomm { - private MediaProvider() { + private Telecomm() { } - private static final String PREFIX = "MediaProvider."; + private static final String PREFIX = "Telecomm."; /** - * 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 + * Missed call notification label, used when there's exactly one missed call from work + * contact. */ - 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; - } + 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 PermissionController module. + * in the Permissions module. */ public static final class PermissionController { - + private PermissionController() { } @@ -2930,69 +1789,6 @@ public final class DevicePolicyResources { */ 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 000000000000..06729222dea1 --- /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 b36f140807aa..7e593406c87c 100644 --- a/core/java/android/app/admin/DevicePolicyStringResource.java +++ b/core/java/android/app/admin/DevicePolicyStringResource.java @@ -28,19 +28,19 @@ import java.util.Objects; /** * 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 final class DevicePolicyStringResource implements Parcelable { */ 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 @@ public final class DevicePolicyStringResource implements Parcelable { /** * 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 40ae1f0c11ea..7e951779d2a6 100644 --- a/core/java/android/app/admin/FactoryResetProtectionPolicy.java +++ b/core/java/android/app/admin/FactoryResetProtectionPolicy.java @@ -25,6 +25,7 @@ import android.annotation.Nullable; 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 @@ public final class FactoryResetProtectionPolicy implements Parcelable { 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 77db14654592..8a9ef4bf9e0e 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 @@ interface IDevicePolicyManager { 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 @@ interface IDevicePolicyManager { 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,17 @@ interface IDevicePolicyManager { 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(); + + List<UserHandle> getPolicyManagedProfiles(in UserHandle userHandle); } diff --git a/core/java/android/app/admin/ParcelableResource.java b/core/java/android/app/admin/ParcelableResource.java index bcae2846ad42..a29766546551 100644 --- a/core/java/android/app/admin/ParcelableResource.java +++ b/core/java/android/app/admin/ParcelableResource.java @@ -43,7 +43,8 @@ import java.util.function.Supplier; /** * 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 51e3953ead4f..91da8ec71dae 100644 --- a/core/java/android/app/prediction/AppTargetEvent.java +++ b/core/java/android/app/prediction/AppTargetEvent.java @@ -60,6 +60,11 @@ public final class AppTargetEvent implements Parcelable { */ 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 e1d37e1b1ae0..572c45355e42 100644 --- a/core/java/android/app/usage/BroadcastResponseStats.java +++ b/core/java/android/app/usage/BroadcastResponseStats.java @@ -29,6 +29,8 @@ import java.util.Objects; * 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 2a2a9c6e703e..d4fbdc6850a4 100644 --- a/core/java/android/app/usage/IUsageStatsManager.aidl +++ b/core/java/android/app/usage/IUsageStatsManager.aidl @@ -74,12 +74,14 @@ interface IUsageStatsManager { 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 3a335f9d151b..c013fcd5adb9 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 @@ public final class UsageStatsManager { * @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 @@ public final class UsageStatsManager { * @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 @@ public final class UsageStatsManager { * * @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 @@ public final class UsageStatsManager { 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 60efb4d3ec81..24b1b6adb450 100644 --- a/core/java/android/content/Context.java +++ b/core/java/android/content/Context.java @@ -6508,22 +6508,22 @@ public abstract class Context { /** - * 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 @@ public abstract class Context { * @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 @@ public abstract class Context { } /** - * 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 9adf17367039..4ecd7761ac4f 100644 --- a/core/java/android/content/ContextWrapper.java +++ b/core/java/android/content/ContextWrapper.java @@ -1036,8 +1036,8 @@ public class ContextWrapper extends Context { } @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 478befd9c26d..a50ff3841da9 100644 --- a/core/java/android/content/Intent.java +++ b/core/java/android/content/Intent.java @@ -5987,22 +5987,6 @@ public class Intent implements Parcelable, Cloneable { 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 class Intent implements Parcelable, Cloneable { 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 @@ public class Intent implements Parcelable, Cloneable { * @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 @@ public class Intent implements Parcelable, Cloneable { * 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 @@ public class Intent implements Parcelable, Cloneable { * 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 @@ public class Intent implements Parcelable, Cloneable { * 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 @@ public class Intent implements Parcelable, Cloneable { * 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 f20d1e62e8e7..1b84686bbfcf 100644 --- a/core/java/android/content/pm/AppSearchShortcutInfo.java +++ b/core/java/android/content/pm/AppSearchShortcutInfo.java @@ -349,7 +349,7 @@ public class AppSearchShortcutInfo extends GenericDocument { .setDisabledReason(shortcutInfo.getDisabledReason()) .setPersons(shortcutInfo.getPersons()) .setLocusId(shortcutInfo.getLocusId()) - .setCapabilityBindings(shortcutInfo.getCapabilityBindings()) + .setCapabilityBindings(shortcutInfo.getCapabilityBindingsInternal()) .setTtlMillis(SHORTCUT_TTL) .build(); } diff --git a/core/java/android/content/pm/Capability.aidl b/core/java/android/content/pm/Capability.aidl new file mode 100644 index 000000000000..df3b1be1ce31 --- /dev/null +++ b/core/java/android/content/pm/Capability.aidl @@ -0,0 +1,18 @@ +/* + * 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; + +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 000000000000..1597d31828a1 --- /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/core/java/android/content/pm/CapabilityParams.aidl b/core/java/android/content/pm/CapabilityParams.aidl new file mode 100644 index 000000000000..39f12387404f --- /dev/null +++ b/core/java/android/content/pm/CapabilityParams.aidl @@ -0,0 +1,18 @@ +/* + * 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; + +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 000000000000..7239bacf1221 --- /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 94f056110bf7..66c6c817e9ea 100644 --- a/core/java/android/content/pm/CrossProfileApps.java +++ b/core/java/android/content/pm/CrossProfileApps.java @@ -104,7 +104,44 @@ public class CrossProfileApps { 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 @@ public class CrossProfileApps { * @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 @@ public class CrossProfileApps { 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 @@ public class CrossProfileApps { 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 e2850f111c4f..4f2c1069275e 100644 --- a/core/java/android/content/pm/ICrossProfileApps.aidl +++ b/core/java/android/content/pm/ICrossProfileApps.aidl @@ -29,7 +29,7 @@ import android.os.UserHandle; 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 eefa63f5b8fa..f4de82946253 100644 --- a/core/java/android/content/pm/PackageInfo.java +++ b/core/java/android/content/pm/PackageInfo.java @@ -213,7 +213,8 @@ public class PackageInfo implements Parcelable { * 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 81c941eedef0..227ac1a02890 100644 --- a/core/java/android/content/pm/PackageManager.java +++ b/core/java/android/content/pm/PackageManager.java @@ -4087,6 +4087,28 @@ public abstract class PackageManager { "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 @@ public abstract class PackageManager { * 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 @@ public abstract class PackageManager { * 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 @@ public abstract class PackageManager { * 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 @@ public abstract class PackageManager { * 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 @@ public abstract class PackageManager { * 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 @@ public abstract class PackageManager { * @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 @@ public abstract class PackageManager { * 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 @@ public abstract class PackageManager { * 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 */ @@ -10297,7 +10319,11 @@ public abstract class PackageManager { /** * Makes the package associated with the uid {@code visibleUid} become visible to the - * recipient uid application. + * recipient application. The recipient application can receive the details about the + * visible package if successful. + * <p> + * Read <a href="/training/basics/intents/package-visibility">package visibility</a> for more + * information. * * @param recipientUid The uid of the application that is being given access to {@code * visibleUid} diff --git a/core/java/android/content/pm/SHORTCUT_OWNERS b/core/java/android/content/pm/SHORTCUT_OWNERS index 3688d5a3a4c7..f8bba473336d 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 41dd5bb3f21d..56d092d8319d 100644 --- a/core/java/android/content/pm/ShortcutInfo.java +++ b/core/java/android/content/pm/ShortcutInfo.java @@ -52,7 +52,7 @@ import com.android.internal.util.Preconditions; 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.Map; 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 @@ public final class ShortcutInfo implements Parcelable { 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 @@ public final class ShortcutInfo implements Parcelable { // Set this bit. mFlags |= FLAG_KEY_FIELDS_ONLY; } - mCapabilityBindings = source.mCapabilityBindings; + mCapabilityBindings = cloneCapabilityBindings( + source.mCapabilityBindings); mStartingThemeResName = source.mStartingThemeResName; } @@ -1003,7 +1004,8 @@ public final class ShortcutInfo implements Parcelable { mStartingThemeResName = source.mStartingThemeResName; } if (source.mCapabilityBindings != null) { - mCapabilityBindings = source.mCapabilityBindings; + mCapabilityBindings = + cloneCapabilityBindings(source.mCapabilityBindings); } } @@ -1447,43 +1449,25 @@ public final class ShortcutInfo implements Parcelable { * <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 (parameterName == null || parameterValues == null || parameterValues.isEmpty()) { - return this; - } - if (parameterName.contains("/")) { - throw new IllegalArgumentException( - "Illegal character '/' is found in parameter name"); + if (!mCapabilityBindings.containsKey(capability.getName())) { + mCapabilityBindings.put(capability.getName(), new ArrayMap<>(0)); } - final Map<String, List<String>> params = mCapabilityBindings.get(capability); - if (!params.containsKey(parameterName)) { - params.put(parameterName, parameterValues); + if (capabilityParams == null) { 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 @@ public final class ShortcutInfo implements Parcelable { } /** + * 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. + * Return a list of {@link Capability} associated with the shortcut. */ - public boolean hasCapability(@NonNull String capability) { - Objects.requireNonNull(capability); - return mCapabilityBindings != null && mCapabilityBindings.containsKey(capability); + @NonNull + public List<Capability> getCapabilities() { + if (mCapabilityBindings == null) { + return new ArrayList<>(0); + } + return mCapabilityBindings.keySet().stream().map(Capability::new) + .collect(Collectors.toList()); } /** - * Returns the values of specified parameter in associated with given capability. + * Returns the {@link CapabilityParams} 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. + * @param capability {@link Capability} associated with the shortcut. */ @NonNull - public List<String> getCapabilityParameterValues( - @NonNull String capability, @NonNull String parameterName) { + public List<CapabilityParams> getCapabilityParams(@NonNull final Capability capability) { Objects.requireNonNull(capability); - Objects.requireNonNull(parameterName); if (mCapabilityBindings == null) { - return Collections.emptyList(); - } - final Map<String, List<String>> param = mCapabilityBindings.get(capability); - if (param == null || !param.containsKey(parameterName)) { - return Collections.emptyList(); + return new ArrayList<>(0); + } + 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 param.get(parameterName); + return ret; } private ShortcutInfo(Parcel source) { @@ -2357,7 +2378,7 @@ public final class ShortcutInfo implements Parcelable { 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 @@ public final class ShortcutInfo implements Parcelable { 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 7459a9029212..ee9aaca3ed43 100644 --- a/core/java/android/content/pm/SigningInfo.java +++ b/core/java/android/content/pm/SigningInfo.java @@ -72,9 +72,11 @@ public final class SigningInfo implements Parcelable { /** * 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 a05f5c927b29..c8bbb0c1994d 100644 --- a/core/java/android/content/res/AssetManager.java +++ b/core/java/android/content/res/AssetManager.java @@ -79,6 +79,13 @@ public final class AssetManager implements AutoCloseable { @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 7b24cc4836d0..3952467324fe 100644 --- a/core/java/android/hardware/CameraStreamStats.java +++ b/core/java/android/hardware/CameraStreamStats.java @@ -49,7 +49,7 @@ public class CameraStreamStats implements Parcelable { 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 class CameraStreamStats implements Parcelable { 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 @@ public class CameraStreamStats implements Parcelable { dest.writeFloatArray(mHistogramBins); dest.writeLongArray(mHistogramCounts); dest.writeLong(mDynamicRangeProfile); - dest.writeInt(mStreamUseCase); + dest.writeLong(mStreamUseCase); } public void readFromParcel(Parcel in) { @@ -154,7 +154,7 @@ public class CameraStreamStats implements Parcelable { mHistogramBins = in.createFloatArray(); mHistogramCounts = in.createLongArray(); mDynamicRangeProfile = in.readLong(); - mStreamUseCase = in.readInt(); + mStreamUseCase = in.readLong(); } public int getWidth() { @@ -217,7 +217,7 @@ public class CameraStreamStats implements Parcelable { 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 cd4bf78f0879..166001347bd4 100644 --- a/core/java/android/hardware/SyncFence.java +++ b/core/java/android/hardware/SyncFence.java @@ -24,6 +24,7 @@ import android.opengl.EGLSync; import android.os.Parcel; import android.os.ParcelFileDescriptor; import android.os.Parcelable; +import android.os.SystemClock; import libcore.util.NativeAllocationRegistry; @@ -105,6 +106,21 @@ public final class SyncFence implements AutoCloseable, Parcelable { } } + /** + * 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 @@ public final class SyncFence implements AutoCloseable, Parcelable { } /** - * 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 7bebe1ff14c3..b05e6d131957 100644 --- a/core/java/android/hardware/camera2/CameraCharacteristics.java +++ b/core/java/android/hardware/camera2/CameraCharacteristics.java @@ -3563,8 +3563,8 @@ public final class CameraCharacteristics extends CameraMetadata<CameraCharacteri */ @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 465abfb55540..a3bc66546a6a 100644 --- a/core/java/android/hardware/camera2/params/MandatoryStreamCombination.java +++ b/core/java/android/hardware/camera2/params/MandatoryStreamCombination.java @@ -66,7 +66,7 @@ public final class MandatoryStreamCombination { 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 final class MandatoryStreamCombination { */ 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 @@ public final class MandatoryStreamCombination { * 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 @@ public final class MandatoryStreamCombination { /** * 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 @@ public final class MandatoryStreamCombination { 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 2350b7c7a481..39cb7f3ebddb 100644 --- a/core/java/android/hardware/camera2/params/OutputConfiguration.java +++ b/core/java/android/hardware/camera2/params/OutputConfiguration.java @@ -918,9 +918,9 @@ public final class OutputConfiguration implements Parcelable { * @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 @@ public final class OutputConfiguration implements Parcelable { * * @return the currently set stream use case */ - public int getStreamUseCase() { + public long getStreamUseCase() { return mStreamUseCase; } @@ -1067,7 +1067,7 @@ public final class OutputConfiguration implements Parcelable { 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 @@ public final class OutputConfiguration implements Parcelable { // 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 @@ public final class OutputConfiguration implements Parcelable { // 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 7e070bc06056..29221b801ef6 100644 --- a/core/java/android/hardware/fingerprint/FingerprintManager.java +++ b/core/java/android/hardware/fingerprint/FingerprintManager.java @@ -923,14 +923,15 @@ public class FingerprintManager implements BiometricAuthenticator, BiometricFing * @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 @@ public class FingerprintManager implements BiometricAuthenticator, BiometricFing * @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 @@ public class FingerprintManager implements BiometricAuthenticator, BiometricFing * @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 cbff8b11a72a..12114aa3fa33 100644 --- a/core/java/android/hardware/fingerprint/IFingerprintService.aidl +++ b/core/java/android/hardware/fingerprint/IFingerprintService.aidl @@ -155,13 +155,13 @@ interface IFingerprintService { 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 3cca1b38e5e2..dbb8e40f3a71 100644 --- a/core/java/android/hardware/fingerprint/IUdfpsOverlayController.aidl +++ b/core/java/android/hardware/fingerprint/IUdfpsOverlayController.aidl @@ -23,7 +23,7 @@ import android.hardware.fingerprint.IUdfpsOverlayControllerCallback; */ 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 0f9075b498ae..03d11515c0a8 100644 --- a/core/java/android/inputmethodservice/NavigationBarController.java +++ b/core/java/android/inputmethodservice/NavigationBarController.java @@ -294,8 +294,8 @@ final class NavigationBarController { 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 4cfd8139d912..382b6b074962 100644 --- a/core/java/android/inputmethodservice/navigationbar/DeadZone.java +++ b/core/java/android/inputmethodservice/navigationbar/DeadZone.java @@ -148,7 +148,7 @@ final class DeadZone { 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 cfdb6caab9d3..92d358fe1663 100644 --- a/core/java/android/inputmethodservice/navigationbar/KeyButtonView.java +++ b/core/java/android/inputmethodservice/navigationbar/KeyButtonView.java @@ -89,7 +89,7 @@ public class KeyButtonView extends ImageView implements ButtonInterface { 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 @@ public class KeyButtonView extends ImageView implements ButtonInterface { 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 070efa363cc0..b4647cabe1bc 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 @@ interface IVpnManager { 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 0fd3e034291b..3abe83bd3373 100644 --- a/core/java/android/net/Ikev2VpnProfile.java +++ b/core/java/android/net/Ikev2VpnProfile.java @@ -142,6 +142,7 @@ public final class Ikev2VpnProfile extends PlatformVpnProfile { 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 @@ public final class Ikev2VpnProfile extends PlatformVpnProfile { 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 @@ public final class Ikev2VpnProfile extends PlatformVpnProfile { mMaxMtu = maxMtu; mIsRestrictedToTestNetworks = restrictToTestNetworks; + mIkeTunConnParams = ikeTunConnParams; + validate(); } @@ -375,6 +379,12 @@ public final class Ikev2VpnProfile extends PlatformVpnProfile { 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 @@ public final class Ikev2VpnProfile extends PlatformVpnProfile { mMaxMtu, mIsRestrictedToTestNetworks, mExcludeLocalRoutes, - mRequiresInternetValidation); + mRequiresInternetValidation, + mIkeTunConnParams); } @Override @@ -429,7 +440,8 @@ public final class Ikev2VpnProfile extends PlatformVpnProfile { && mMaxMtu == other.mMaxMtu && mIsRestrictedToTestNetworks == other.mIsRestrictedToTestNetworks && mExcludeLocalRoutes == other.mExcludeLocalRoutes - && mRequiresInternetValidation == other.mRequiresInternetValidation; + && mRequiresInternetValidation == other.mRequiresInternetValidation + && Objects.equals(mIkeTunConnParams, other.mIkeTunConnParams); } /** @@ -504,6 +516,7 @@ public final class Ikev2VpnProfile extends PlatformVpnProfile { @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 @@ public final class Ikev2VpnProfile extends PlatformVpnProfile { 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 @@ public final class Ikev2VpnProfile extends PlatformVpnProfile { mServerAddr = serverAddr; mUserIdentity = identity; + + mIkeTunConnParams = null; } /** @@ -1135,7 +1150,8 @@ public final class Ikev2VpnProfile extends PlatformVpnProfile { mMaxMtu, mIsRestrictedToTestNetworks, mExcludeLocalRoutes, - mRequiresInternetValidation); + mRequiresInternetValidation, + mIkeTunConnParams); } } } diff --git a/core/java/android/net/NetworkPolicyManager.java b/core/java/android/net/NetworkPolicyManager.java index 18ec8f57ad3a..2c2a703b16e2 100644 --- a/core/java/android/net/NetworkPolicyManager.java +++ b/core/java/android/net/NetworkPolicyManager.java @@ -580,6 +580,24 @@ public class NetworkPolicyManager { } /** + * 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 @@ public class NetworkPolicyManager { 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 0eb4cf3ecadf..b05f7cf241e3 100644 --- a/core/java/android/net/SntpClient.java +++ b/core/java/android/net/SntpClient.java @@ -60,7 +60,7 @@ public class SntpClient { 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 @@ public class SntpClient { * 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 c51444cd31b6..ae7d91f92cb7 100644 --- a/core/java/android/net/VpnManager.java +++ b/core/java/android/net/VpnManager.java @@ -161,6 +161,23 @@ public class VpnManager { "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 @@ public class VpnManager { } /** + * 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/core/java/android/net/VpnProfileState.aidl b/core/java/android/net/VpnProfileState.aidl new file mode 100644 index 000000000000..add6386eda75 --- /dev/null +++ b/core/java/android/net/VpnProfileState.aidl @@ -0,0 +1,19 @@ +/* + * Copyright (C) 2022 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.net; + +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 000000000000..c69ea1a8c220 --- /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 2dd3aaa1f55a..5c9989e9d981 100644 --- a/core/java/android/net/netstats/NetworkStatsDataMigrationUtils.java +++ b/core/java/android/net/netstats/NetworkStatsDataMigrationUtils.java @@ -27,6 +27,7 @@ import static android.net.NetworkStats.TAG_NONE; 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.File; 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 class NetworkStatsDataMigrationUtils { */ 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 @@ public class NetworkStatsDataMigrationUtils { // 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 @@ public class NetworkStatsDataMigrationUtils { */ @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 de76c8fab69b..f4ca1b50fe86 100644 --- a/core/java/android/os/BatteryConsumer.java +++ b/core/java/android/os/BatteryConsumer.java @@ -165,6 +165,7 @@ public abstract class BatteryConsumer { PROCESS_STATE_FOREGROUND, PROCESS_STATE_BACKGROUND, PROCESS_STATE_FOREGROUND_SERVICE, + PROCESS_STATE_CACHED, }) @Retention(RetentionPolicy.SOURCE) public @interface ProcessState { @@ -175,8 +176,9 @@ public abstract class BatteryConsumer { 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 @@ public abstract class BatteryConsumer { 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 5f9fdbfe7503..06c35b5bec5d 100644 --- a/core/java/android/os/BatteryStats.java +++ b/core/java/android/os/BatteryStats.java @@ -680,6 +680,8 @@ public abstract class BatteryStats implements Parcelable { 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 abstract class BatteryStats implements Parcelable { 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 @@ public abstract class BatteryStats implements Parcelable { @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 abstract class BatteryStats implements Parcelable { 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 @@ public abstract class BatteryStats implements Parcelable { " 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 @@ public abstract class BatteryStats implements Parcelable { 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/Build.java b/core/java/android/os/Build.java index 1c85f692b232..42e6ac4df8af 100755 --- a/core/java/android/os/Build.java +++ b/core/java/android/os/Build.java @@ -406,7 +406,7 @@ public class Build { public static final String CODENAME = getString("ro.build.version.codename"); /** - * All known codenames starting from {@link VERSION_CODES.Q}. + * All known codenames that are present in {@link VERSION_CODES}. * * <p>This includes in development codenames as well, i.e. if {@link #CODENAME} is not "REL" * then the value of that is present in this set. diff --git a/core/java/android/os/IpcDataCache.java b/core/java/android/os/IpcDataCache.java index 00734c806b7e..0efa34cdc47f 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 @@ public class IpcDataCache<Query, Result> extends PropertyInvalidatedCache<Query, }; /** + * 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 @@ public class IpcDataCache<Query, Result> extends PropertyInvalidatedCache<Query, */ @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 @@ public class IpcDataCache<Query, Result> extends PropertyInvalidatedCache<Query, */ @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 368ee2d91172..a739ba3dd438 100644 --- a/core/java/android/os/ParcelableHolder.java +++ b/core/java/android/os/ParcelableHolder.java @@ -179,7 +179,11 @@ public final class ParcelableHolder implements Parcelable { * 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 605171208fc1..522807b83d04 100644 --- a/core/java/android/os/PowerComponents.java +++ b/core/java/android/os/PowerComponents.java @@ -292,6 +292,10 @@ class PowerComponents { 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 77d1498e1597..91d231eb1c39 100644 --- a/core/java/android/os/UidBatteryConsumer.java +++ b/core/java/android/os/UidBatteryConsumer.java @@ -119,6 +119,8 @@ public final class UidBatteryConsumer extends BatteryConsumer { 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 276578ea3c1f..608c424451b7 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 @@ public class UserManager { /** * 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 @@ public class UserManager { 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 @@ public class UserManager { 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 @@ public class UserManager { * 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 @@ public class UserManager { } /** + * 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 7832dccd93a5..a0f6598640ba 100644 --- a/core/java/android/os/storage/IStorageManager.aidl +++ b/core/java/android/os/storage/IStorageManager.aidl @@ -78,37 +78,10 @@ interface IStorageManager { */ 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 @@ interface IStorageManager { */ 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 @@ interface IStorageManager { 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 312abf877f53..9971cbcfa586 100644 --- a/core/java/android/os/storage/StorageManager.java +++ b/core/java/android/os/storage/StorageManager.java @@ -3044,14 +3044,4 @@ public class StorageManager { 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 c9dd06cfaa43..e3f02e73a41f 100644 --- a/core/java/android/permission/IPermissionController.aidl +++ b/core/java/android/permission/IPermissionController.aidl @@ -59,6 +59,6 @@ oneway interface IPermissionController { 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 619c8705ddae..6a93b354f4da 100644 --- a/core/java/android/permission/IPermissionManager.aidl +++ b/core/java/android/permission/IPermissionManager.aidl @@ -76,8 +76,6 @@ interface IPermissionManager { 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 a005ab4e6ac7..3c2c7f03761b 100644 --- a/core/java/android/permission/PermissionControllerManager.java +++ b/core/java/android/permission/PermissionControllerManager.java @@ -916,15 +916,15 @@ public final class PermissionControllerManager { * @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 3292e7110ee5..4efffc5a11ef 100644 --- a/core/java/android/permission/PermissionControllerService.java +++ b/core/java/android/permission/PermissionControllerService.java @@ -40,6 +40,7 @@ import android.compat.annotation.Disabled; 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 @@ public abstract class PermissionControllerService extends Service { * @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 @@ public abstract class PermissionControllerService extends Service { } @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 c509de6bb5e1..7a797ce28870 100644 --- a/core/java/android/permission/PermissionManager.java +++ b/core/java/android/permission/PermissionManager.java @@ -76,7 +76,6 @@ import com.android.internal.annotations.Immutable; 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 @@ public final class PermissionManager { } /** - * @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 0b57842cde11..4ed939c48bd7 100644 --- a/core/java/android/permission/PermissionUsageHelper.java +++ b/core/java/android/permission/PermissionUsageHelper.java @@ -47,6 +47,7 @@ import android.content.pm.PackageInfo; 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 @@ public class PermissionUsageHelper implements AppOpsManager.OnOpActiveChangedLis } /** - * 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 @@ public class PermissionUsageHelper implements AppOpsManager.OnOpActiveChangedLis } /** + * @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 1008a2d0ad1a..47315047b6c4 100644 --- a/core/java/android/provider/DeviceConfig.java +++ b/core/java/android/provider/DeviceConfig.java @@ -600,6 +600,13 @@ public final class DeviceConfig { 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 a6ad5e5863df..5191c9583379 100644 --- a/core/java/android/provider/Settings.java +++ b/core/java/android/provider/Settings.java @@ -2143,10 +2143,10 @@ public final class Settings { /** * 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 @@ public final class Settings { "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 227194e60a7e..a216ed501687 100644 --- a/core/java/android/service/ambientcontext/AmbientContextDetectionResult.java +++ b/core/java/android/service/ambientcontext/AmbientContextDetectionResult.java @@ -26,6 +26,7 @@ import com.android.internal.util.AnnotationValidations; 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 @@ public final class AmbientContextDetectionResult implements Parcelable { private @NonNull String mPackageName; private long mBuilderFieldsSet = 0L; - public Builder() { + public Builder(@NonNull String packageName) { + Objects.requireNonNull(packageName); + mPackageName = packageName; } /** @@ -144,26 +147,37 @@ public final class AmbientContextDetectionResult implements Parcelable { } /** - * 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 @@ public final class AmbientContextDetectionResult implements Parcelable { } 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 6224aa1d102e..8cf34115c6c4 100644 --- a/core/java/android/service/ambientcontext/AmbientContextDetectionService.java +++ b/core/java/android/service/ambientcontext/AmbientContextDetectionService.java @@ -134,12 +134,18 @@ public abstract class AmbientContextDetectionService extends Service { } /** - * 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 3e92f39893de..199e674e4b54 100644 --- a/core/java/android/service/ambientcontext/AmbientContextDetectionServiceStatus.java +++ b/core/java/android/service/ambientcontext/AmbientContextDetectionServiceStatus.java @@ -24,6 +24,8 @@ import android.os.Parcelable; import com.android.internal.util.AnnotationValidations; +import java.util.Objects; + /** * Represents a status for the {@code AmbientContextDetectionService}. * @@ -121,7 +123,9 @@ public final class AmbientContextDetectionServiceStatus implements Parcelable { private @NonNull String mPackageName; private long mBuilderFieldsSet = 0L; - public Builder() { + public Builder(@NonNull String packageName) { + Objects.requireNonNull(packageName); + mPackageName = packageName; } /** @@ -134,27 +138,14 @@ public final class AmbientContextDetectionServiceStatus implements Parcelable { 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 @@ public final class AmbientContextDetectionServiceStatus implements Parcelable { } 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/FillEventHistory.java b/core/java/android/service/autofill/FillEventHistory.java index 7a8f6f415fbf..0fb9f57f5f57 100644 --- a/core/java/android/service/autofill/FillEventHistory.java +++ b/core/java/android/service/autofill/FillEventHistory.java @@ -160,6 +160,7 @@ public final class FillEventHistory implements Parcelable { event.mDetectedFieldClassifications); } parcel.writeInt(event.mSaveDialogNotShowReason); + parcel.writeInt(event.mUiType); } } } @@ -278,6 +279,29 @@ public final class FillEventHistory implements Parcelable { @Retention(RetentionPolicy.SOURCE) public @interface NoSaveReason{} + /** The autofill suggestion presentation is unknown, this will be set for the event + * that is unrelated to fill Ui presentation */ + public static final int UI_TYPE_UNKNOWN = 0; + + /** The autofill suggestion is shown as a menu popup presentation. */ + public static final int UI_TYPE_MENU = 1; + + /** The autofill suggestion is shown as a keyboard inline presentation. */ + public static final int UI_TYPE_INLINE = 2; + + /** The autofill suggestion is shown as a dialog presentation. */ + public static final int UI_TYPE_DIALOG = 3; + + /** @hide */ + @IntDef(prefix = { "UI_TYPE_" }, value = { + UI_TYPE_UNKNOWN, + UI_TYPE_MENU, + UI_TYPE_INLINE, + UI_TYPE_DIALOG + }) + @Retention(RetentionPolicy.SOURCE) + public @interface UiType {} + @EventIds private final int mEventType; @Nullable private final String mDatasetId; @Nullable private final Bundle mClientState; @@ -298,6 +322,10 @@ public final class FillEventHistory implements Parcelable { @NoSaveReason private final int mSaveDialogNotShowReason; + + @UiType + private final int mUiType; + /** * Returns the type of the event. * @@ -498,6 +526,21 @@ public final class FillEventHistory implements Parcelable { } /** + * Returns fill suggestion ui presentation type which corresponds to types + * defined in {@link android.service.autofill.Presentations). + * + * <p><b>Note: </b>Only set on events of type {@link #TYPE_DATASETS_SHOWN} and + * {@link #TYPE_DATASET_SELECTED}. For the other event types, the type is set to + * {@link #UI_TYPE_UNKNOWN }. + * + * @return The ui presentation type shown for user. + */ + @UiType + public int getUiType() { + return mUiType; + } + + /** * Creates a new event. * * @param eventType The type of the event @@ -573,6 +616,49 @@ public final class FillEventHistory implements Parcelable { @Nullable AutofillId[] detectedFieldIds, @Nullable FieldClassification[] detectedFieldClassifications, int saveDialogNotShowReason) { + this(eventType, datasetId, clientState, selectedDatasetIds, ignoredDatasetIds, + changedFieldIds, changedDatasetIds, manuallyFilledFieldIds, + manuallyFilledDatasetIds, detectedFieldIds, detectedFieldClassifications, + saveDialogNotShowReason, UI_TYPE_UNKNOWN); + } + + /** + * Creates a new event. + * + * @param eventType The type of the event + * @param datasetId The dataset the event was on, or {@code null} if the event was on the + * whole response. + * @param clientState The client state associated with the event. + * @param selectedDatasetIds The ids of datasets selected by the user. + * @param ignoredDatasetIds The ids of datasets NOT select by the user. + * @param changedFieldIds The ids of fields changed by the user. + * @param changedDatasetIds The ids of the datasets that havd values matching the + * respective entry on {@code changedFieldIds}. + * @param manuallyFilledFieldIds The ids of fields that were manually entered by the user + * and belonged to datasets. + * @param manuallyFilledDatasetIds The ids of datasets that had values matching the + * respective entry on {@code manuallyFilledFieldIds}. + * @param detectedFieldClassifications the field classification matches. + * @param saveDialogNotShowReason The reason why a save dialog was not shown. + * @param uiType The ui presentation type for fill suggestion. + * + * @throws IllegalArgumentException If the length of {@code changedFieldIds} and + * {@code changedDatasetIds} doesn't match. + * @throws IllegalArgumentException If the length of {@code manuallyFilledFieldIds} and + * {@code manuallyFilledDatasetIds} doesn't match. + * + * @hide + */ + public Event(int eventType, @Nullable String datasetId, @Nullable Bundle clientState, + @Nullable List<String> selectedDatasetIds, + @Nullable ArraySet<String> ignoredDatasetIds, + @Nullable ArrayList<AutofillId> changedFieldIds, + @Nullable ArrayList<String> changedDatasetIds, + @Nullable ArrayList<AutofillId> manuallyFilledFieldIds, + @Nullable ArrayList<ArrayList<String>> manuallyFilledDatasetIds, + @Nullable AutofillId[] detectedFieldIds, + @Nullable FieldClassification[] detectedFieldClassifications, + int saveDialogNotShowReason, int uiType) { mEventType = Preconditions.checkArgumentInRange(eventType, 0, TYPE_DATASETS_SHOWN, "eventType"); mDatasetId = datasetId; @@ -581,16 +667,16 @@ public final class FillEventHistory implements Parcelable { mIgnoredDatasetIds = ignoredDatasetIds; if (changedFieldIds != null) { Preconditions.checkArgument(!ArrayUtils.isEmpty(changedFieldIds) - && changedDatasetIds != null - && changedFieldIds.size() == changedDatasetIds.size(), + && changedDatasetIds != null + && changedFieldIds.size() == changedDatasetIds.size(), "changed ids must have same length and not be empty"); } mChangedFieldIds = changedFieldIds; mChangedDatasetIds = changedDatasetIds; if (manuallyFilledFieldIds != null) { Preconditions.checkArgument(!ArrayUtils.isEmpty(manuallyFilledFieldIds) - && manuallyFilledDatasetIds != null - && manuallyFilledFieldIds.size() == manuallyFilledDatasetIds.size(), + && manuallyFilledDatasetIds != null + && manuallyFilledFieldIds.size() == manuallyFilledDatasetIds.size(), "manually filled ids must have same length and not be empty"); } mManuallyFilledFieldIds = manuallyFilledFieldIds; @@ -602,12 +688,14 @@ public final class FillEventHistory implements Parcelable { mSaveDialogNotShowReason = Preconditions.checkArgumentInRange(saveDialogNotShowReason, NO_SAVE_UI_REASON_NONE, NO_SAVE_UI_REASON_DATASET_MATCH, "saveDialogNotShowReason"); + mUiType = uiType; } @Override public String toString() { return "FillEvent [datasetId=" + mDatasetId - + ", type=" + mEventType + + ", type=" + eventToString(mEventType) + + ", uiType=" + uiTypeToString(mUiType) + ", selectedDatasets=" + mSelectedDatasetIds + ", ignoredDatasetIds=" + mIgnoredDatasetIds + ", changedFieldIds=" + mChangedFieldIds @@ -620,6 +708,38 @@ public final class FillEventHistory implements Parcelable { + ", saveDialogNotShowReason=" + mSaveDialogNotShowReason + "]"; } + + private static String eventToString(int eventType) { + switch (eventType) { + case TYPE_DATASET_SELECTED: + return "TYPE_DATASET_SELECTED"; + case TYPE_DATASET_AUTHENTICATION_SELECTED: + return "TYPE_DATASET_AUTHENTICATION_SELECTED"; + case TYPE_AUTHENTICATION_SELECTED: + return "TYPE_AUTHENTICATION_SELECTED"; + case TYPE_SAVE_SHOWN: + return "TYPE_SAVE_SHOWN"; + case TYPE_CONTEXT_COMMITTED: + return "TYPE_CONTEXT_COMMITTED"; + case TYPE_DATASETS_SHOWN: + return "TYPE_DATASETS_SHOWN"; + default: + return "TYPE_UNKNOWN"; + } + } + + private static String uiTypeToString(int uiType) { + switch (uiType) { + case UI_TYPE_MENU: + return "UI_TYPE_MENU"; + case UI_TYPE_INLINE: + return "UI_TYPE_INLINE"; + case UI_TYPE_DIALOG: + return "UI_TYPE_FILL_DIALOG"; + default: + return "UI_TYPE_UNKNOWN"; + } + } } public static final @android.annotation.NonNull Parcelable.Creator<FillEventHistory> CREATOR = @@ -660,13 +780,14 @@ public final class FillEventHistory implements Parcelable { ? FieldClassification.readArrayFromParcel(parcel) : null; final int saveDialogNotShowReason = parcel.readInt(); + final int uiType = parcel.readInt(); selection.addEvent(new Event(eventType, datasetId, clientState, selectedDatasetIds, ignoredDatasets, changedFieldIds, changedDatasetIds, manuallyFilledFieldIds, manuallyFilledDatasetIds, detectedFieldIds, detectedFieldClassifications, - saveDialogNotShowReason)); + saveDialogNotShowReason, uiType)); } return selection; } diff --git a/core/java/android/service/autofill/FillRequest.java b/core/java/android/service/autofill/FillRequest.java index e4d3732361ed..c73ebed3c368 100644 --- a/core/java/android/service/autofill/FillRequest.java +++ b/core/java/android/service/autofill/FillRequest.java @@ -100,10 +100,10 @@ public final class FillRequest implements Parcelable { // 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 @@ public final class FillRequest implements Parcelable { /** * 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 @@ public final class FillRequest implements Parcelable { 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 @@ public final class FillRequest implements Parcelable { 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 @@ public final class FillRequest implements Parcelable { * @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 @@ public final class FillRequest implements Parcelable { | 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 @@ public final class FillRequest implements Parcelable { /** * 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 @@ public final class FillRequest implements Parcelable { | 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 @@ public final class FillRequest implements Parcelable { }; @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 f22d40ea4d5e..3fac23b61a4b 100644 --- a/core/java/android/service/displayhash/DisplayHashingService.java +++ b/core/java/android/service/displayhash/DisplayHashingService.java @@ -68,9 +68,6 @@ public abstract class DisplayHashingService extends Service { 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 1548f5224572..01152943efe3 100644 --- a/core/java/android/service/games/GameSession.java +++ b/core/java/android/service/games/GameSession.java @@ -426,6 +426,7 @@ public abstract class GameSession { * 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/gatekeeper/GateKeeperResponse.java b/core/java/android/service/gatekeeper/GateKeeperResponse.java index 7ed733cb4f4c..9d648a6995fb 100644 --- a/core/java/android/service/gatekeeper/GateKeeperResponse.java +++ b/core/java/android/service/gatekeeper/GateKeeperResponse.java @@ -105,7 +105,7 @@ public final class GateKeeperResponse implements Parcelable { dest.writeInt(mTimeout); } else if (mResponseCode == RESPONSE_OK) { dest.writeInt(mShouldReEnroll ? 1 : 0); - if (mPayload != null) { + if (mPayload != null && mPayload.length > 0) { dest.writeInt(mPayload.length); dest.writeByteArray(mPayload); } else { diff --git a/core/java/android/service/voice/AlwaysOnHotwordDetector.java b/core/java/android/service/voice/AlwaysOnHotwordDetector.java index bec5d1be57fd..bc42da6b4c97 100644 --- a/core/java/android/service/voice/AlwaysOnHotwordDetector.java +++ b/core/java/android/service/voice/AlwaysOnHotwordDetector.java @@ -851,7 +851,8 @@ public class AlwaysOnHotwordDetector extends AbstractHotwordDetector { @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 @@ public class AlwaysOnHotwordDetector extends AbstractHotwordDetector { 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 a2938a8783eb..317408387526 100644 --- a/core/java/android/service/wallpaper/WallpaperService.java +++ b/core/java/android/service/wallpaper/WallpaperService.java @@ -252,6 +252,7 @@ public abstract class WallpaperService extends Service { 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 @@ public abstract class WallpaperService extends Service { @Override public void resized(ClientWindowFrames frames, boolean reportDraw, MergedConfiguration mergedConfiguration, boolean forceLayout, - boolean alwaysConsumeSystemBars, int displayId) { + boolean alwaysConsumeSystemBars, int displayId, int syncSeqId, int resizeMode) { Message msg = mCaller.obtainMessageIO(MSG_WINDOW_RESIZED, reportDraw ? 1 : 0, mergedConfiguration); @@ -1151,7 +1152,7 @@ public abstract class WallpaperService extends Service { 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 @@ public abstract class WallpaperService extends Service { 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 9307e566b5c3..f31a690c7774 100644 --- a/core/java/android/text/PrecomputedText.java +++ b/core/java/android/text/PrecomputedText.java @@ -99,7 +99,7 @@ public class PrecomputedText implements Spannable { 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 @@ public class PrecomputedText implements Spannable { 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 @@ public class PrecomputedText implements Spannable { // 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 @@ public class PrecomputedText implements Spannable { } /** - * 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 @@ public class PrecomputedText implements Spannable { /** @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 @@ public class PrecomputedText implements Spannable { } /** - * 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 b10fc37bff2f..2f85d2b63840 100644 --- a/core/java/android/text/StaticLayout.java +++ b/core/java/android/text/StaticLayout.java @@ -112,6 +112,7 @@ public class StaticLayout extends Layout { 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 @@ public class StaticLayout extends Layout { * * @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 @@ public class StaticLayout extends Layout { @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 34e7ea74a2db..fe6ae78ccf2d 100644 --- a/core/java/android/util/FeatureFlagUtils.java +++ b/core/java/android/util/FeatureFlagUtils.java @@ -96,7 +96,7 @@ public class FeatureFlagUtils { 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 5bb263a1f463..e3bc510b8e40 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 @@ public class IconDrawableFactory { } 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 aebc5e86605a..01a037ae3495 100644 --- a/core/java/android/util/NtpTrustedTime.java +++ b/core/java/android/util/NtpTrustedTime.java @@ -140,6 +140,10 @@ public class NtpTrustedTime implements TrustedTime { /** 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 @@ public class NtpTrustedTime implements TrustedTime { * 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 @@ public class NtpTrustedTime implements TrustedTime { 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 @@ public class NtpTrustedTime implements TrustedTime { 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 @@ public class NtpTrustedTime implements TrustedTime { return mServer; } + @NonNull + public int getPort() { + return mPort; + } + int getTimeoutMillis() { return mTimeoutMillis; } @@ -317,6 +331,7 @@ public class NtpTrustedTime implements TrustedTime { public String toString() { return "NtpConnectionInfo{" + "mServer='" + mServer + '\'' + + ", mPort='" + mPort + '\'' + ", mTimeoutMillis=" + mTimeoutMillis + '}'; } @@ -341,6 +356,13 @@ public class NtpTrustedTime implements TrustedTime { } } + 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 @@ public class NtpTrustedTime implements TrustedTime { 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 066709fd8744..48a5ceae1aef 100644 --- a/core/java/android/util/TimingsTraceLog.java +++ b/core/java/android/util/TimingsTraceLog.java @@ -147,7 +147,7 @@ public class TimingsTraceLog { * 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 db4ec1155e64..c66c70af0656 100644 --- a/core/java/android/view/ContentRecordingSession.java +++ b/core/java/android/view/ContentRecordingSession.java @@ -66,10 +66,11 @@ public final class ContentRecordingSession implements Parcelable { 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 @@ public final class ContentRecordingSession implements Parcelable { } /** - * 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 @@ public final class ContentRecordingSession implements Parcelable { } /** - * 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 @@ public final class ContentRecordingSession implements Parcelable { } /** - * 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 @@ public final class ContentRecordingSession implements Parcelable { } @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 c1413beb0143..61098d60566f 100644 --- a/core/java/android/view/HandwritingInitiator.java +++ b/core/java/android/view/HandwritingInitiator.java @@ -55,10 +55,10 @@ public class HandwritingInitiator { */ 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 class HandwritingInitiator { public HandwritingInitiator(@NonNull ViewConfiguration viewConfiguration, @NonNull InputMethodManager inputMethodManager) { mTouchSlop = viewConfiguration.getScaledTouchSlop(); - mTapTimeoutInMillis = ViewConfiguration.getTapTimeout(); + mHandwritingTimeoutInMillis = ViewConfiguration.getLongPressTimeout(); mImm = inputMethodManager; } @@ -145,7 +145,7 @@ public class HandwritingInitiator { final long timeElapsed = motionEvent.getEventTime() - mState.mStylusDownTimeInMillis; - if (timeElapsed > mTapTimeoutInMillis) { + if (timeElapsed > mHandwritingTimeoutInMillis) { reset(); return; } @@ -249,19 +249,19 @@ public class HandwritingInitiator { 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 @@ public class HandwritingInitiator { 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 @@ public class HandwritingInitiator { 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 @@ public class HandwritingInitiator { 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 @@ public class HandwritingInitiator { /** * 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 @@ public class HandwritingInitiator { 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/IPinnedTaskListener.aidl b/core/java/android/view/IPinnedTaskListener.aidl index 7d39ffe182c7..595a846e069a 100644 --- a/core/java/android/view/IPinnedTaskListener.aidl +++ b/core/java/android/view/IPinnedTaskListener.aidl @@ -47,7 +47,7 @@ oneway interface IPinnedTaskListener { * Called when the set of actions for the current PiP activity changes, or when the listener * is first registered to allow the listener to synchronize its state with the controller. */ - void onActionsChanged(in ParceledListSlice<RemoteAction> actions); + void onActionsChanged(in ParceledListSlice<RemoteAction> actions, in RemoteAction closeAction); /** * Called by the window manager to notify the listener that Activity (was or is in pinned mode) diff --git a/core/java/android/view/IWindow.aidl b/core/java/android/view/IWindow.aidl index 12421ed61b33..5dcf3931ecd6 100644 --- a/core/java/android/view/IWindow.aidl +++ b/core/java/android/view/IWindow.aidl @@ -55,7 +55,8 @@ oneway interface IWindow { void resized(in ClientWindowFrames frames, boolean reportDraw, in MergedConfiguration newMergedConfiguration, - boolean forceLayout, boolean alwaysConsumeSystemBars, int displayId); + boolean forceLayout, boolean alwaysConsumeSystemBars, int displayId, + int syncSeqId, int resizeMode); /** * 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 5c7c844ae773..fd8690009a6d 100644 --- a/core/java/android/view/IWindowSession.aidl +++ b/core/java/android/view/IWindowSession.aidl @@ -104,7 +104,8 @@ interface IWindowSession { 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 @@ interface IWindowSession { * 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 64f5668d8c14..da582c5b4b2f 100644 --- a/core/java/android/view/SurfaceControl.java +++ b/core/java/android/view/SurfaceControl.java @@ -64,6 +64,7 @@ import android.util.proto.ProtoOutputStream; 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.Objects; 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 @@ public final class SurfaceControl implements Parcelable { 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 @@ public final class SurfaceControl implements Parcelable { @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 final class SurfaceControl implements Parcelable { 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 final class SurfaceControl implements Parcelable { */ 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 @@ public final class SurfaceControl implements Parcelable { 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 a13579d0acad..406281d4cade 100644 --- a/core/java/android/view/SurfaceControlViewHost.java +++ b/core/java/android/view/SurfaceControlViewHost.java @@ -401,7 +401,7 @@ public class SurfaceControlViewHost { 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 413855639d09..22ccaae9e3c3 100644 --- a/core/java/android/view/SurfaceView.java +++ b/core/java/android/view/SurfaceView.java @@ -50,6 +50,7 @@ import android.view.accessibility.IAccessibilityEmbeddedConnection; 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 @@ public class SurfaceView extends View implements ViewRootImpl.SurfaceChangedCall 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 @@ public class SurfaceView extends View implements ViewRootImpl.SurfaceChangedCall 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 @@ public class SurfaceView extends View implements ViewRootImpl.SurfaceChangedCall } } - private void performDrawFinished(@Nullable Transaction t) { - if (t != null) { - mSyncTransaction.merge(t); - } - - 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); + private void performDrawFinished() { + mDrawFinished = true; + if (mAttachedToWindow) { + mParent.requestTransparentRegion(SurfaceView.this); + invalidate(); } - mPendingReportDraws--; } @Override @@ -438,10 +413,6 @@ public class SurfaceView extends View implements ViewRootImpl.SurfaceChangedCall mGlobalListenersAdded = false; } - while (mPendingReportDraws > 0) { - notifyDrawFinished(); - } - mRequestedVisible = false; updateSurface(); @@ -993,10 +964,17 @@ public class SurfaceView extends View implements ViewRootImpl.SurfaceChangedCall 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 @@ public class SurfaceView extends View implements ViewRootImpl.SurfaceChangedCall 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 @@ public class SurfaceView extends View implements ViewRootImpl.SurfaceChangedCall } } 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 @@ public class SurfaceView extends View implements ViewRootImpl.SurfaceChangedCall } } + 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 @@ public class SurfaceView extends View implements ViewRootImpl.SurfaceChangedCall 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 c2229911bf12..1b8dc706371e 100644 --- a/core/java/android/view/View.java +++ b/core/java/android/view/View.java @@ -12016,7 +12016,6 @@ public class View implements Drawable.Callback, KeyEvent.Callback, /** * 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 class View implements Drawable.Callback, KeyEvent.Callback, public Rect getHandwritingArea() { final ListenerInfo info = mListenerInfo; if (info != null) { - return info.mHandwritingArea; + return new Rect(info.mHandwritingArea); } return null; } @@ -15617,7 +15616,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback, * @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 @@ public class View implements Drawable.Callback, KeyEvent.Callback, * @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 e79bdcef3507..d15b2a457bfb 100644 --- a/core/java/android/view/ViewRootImpl.java +++ b/core/java/android/view/ViewRootImpl.java @@ -53,8 +53,8 @@ import static android.view.ViewRootImplProto.WIDTH; import static android.view.ViewRootImplProto.WINDOW_ATTRIBUTES; import static android.view.ViewRootImplProto.WIN_FRAME; import static android.view.ViewTreeObserver.InternalInsetsInfo.TOUCHABLE_INSETS_REGION; -import static android.view.WindowCallbacks.RESIZE_MODE_DOCKED_DIVIDER; import static android.view.WindowCallbacks.RESIZE_MODE_FREEFORM; +import static android.view.WindowCallbacks.RESIZE_MODE_INVALID; import static android.view.WindowInsetsController.APPEARANCE_LIGHT_NAVIGATION_BARS; import static android.view.WindowInsetsController.APPEARANCE_LIGHT_STATUS_BARS; import static android.view.WindowInsetsController.APPEARANCE_LOW_PROFILE_BARS; @@ -85,8 +85,6 @@ import static android.view.WindowManager.LayoutParams.TYPE_STATUS_BAR_ADDITIONAL import static android.view.WindowManager.LayoutParams.TYPE_SYSTEM_ALERT; import static android.view.WindowManager.LayoutParams.TYPE_TOAST; import static android.view.WindowManager.LayoutParams.TYPE_VOLUME_OVERLAY; -import static android.view.WindowManagerGlobal.RELAYOUT_RES_DRAG_RESIZING_DOCKED; -import static android.view.WindowManagerGlobal.RELAYOUT_RES_DRAG_RESIZING_FREEFORM; import static android.view.WindowManagerGlobal.RELAYOUT_RES_SURFACE_CHANGED; import static android.view.inputmethod.InputMethodEditorTraceProto.InputMethodClientsTraceProto.ClientSideProto.IME_FOCUS_CONTROLLER; import static android.view.inputmethod.InputMethodEditorTraceProto.InputMethodClientsTraceProto.ClientSideProto.INSETS_CONTROLLER; @@ -503,9 +501,10 @@ public final class ViewRootImpl implements ViewParent, public boolean mIsAnimating; private boolean mUseMTRenderer; + private boolean mPendingDragResizing; private boolean mDragResizing; private boolean mInvalidateRootRequested; - private int mResizeMode; + private int mResizeMode = RESIZE_MODE_INVALID; private int mCanvasOffsetX; private int mCanvasOffsetY; private boolean mActivityRelaunched; @@ -552,7 +551,6 @@ public final class ViewRootImpl implements ViewParent, 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 +582,15 @@ public final class ViewRootImpl implements ViewParent, 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 +811,10 @@ public final class ViewRootImpl implements ViewParent, 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 +836,25 @@ public final class ViewRootImpl implements ViewParent, 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 +1230,7 @@ public final class ViewRootImpl implements ViewParent, 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)) { @@ -1686,17 +1710,22 @@ public final class ViewRootImpl implements ViewParent, final MergedConfiguration mergedConfiguration = (MergedConfiguration) args.arg2; final boolean forceNextWindowRelayout = args.argi1 != 0; final int displayId = args.argi3; + final int resizeMode = args.argi5; final Rect backdropFrame = frames.backdropFrame; final boolean frameChanged = !mWinFrame.equals(frames.frame); final boolean backdropFrameChanged = !mPendingBackDropFrame.equals(backdropFrame); final boolean configChanged = !mLastReportedMergedConfiguration.equals(mergedConfiguration); final boolean displayChanged = mDisplay.getDisplayId() != displayId; + final boolean resizeModeChanged = mResizeMode != resizeMode; if (msg == MSG_RESIZED && !frameChanged && !backdropFrameChanged && !configChanged - && !displayChanged && !forceNextWindowRelayout) { + && !displayChanged && !resizeModeChanged && !forceNextWindowRelayout) { return; } + mPendingDragResizing = resizeMode != RESIZE_MODE_INVALID; + mResizeMode = resizeMode; + if (configChanged) { // If configuration changed - notify about that and, maybe, about move to display. performConfigurationChange(mergedConfiguration, false /* force */, @@ -1711,6 +1740,7 @@ public final class ViewRootImpl implements ViewParent, mPendingBackDropFrame.set(backdropFrame); mForceNextWindowRelayout = forceNextWindowRelayout; mPendingAlwaysConsumeSystemBars = args.argi2 != 0; + mSyncSeqId = args.argi4; if (msg == MSG_RESIZED_REPORT) { reportNextDraw(); @@ -2863,8 +2893,6 @@ public final class ViewRootImpl implements ViewParent, mView.onSystemBarAppearanceChanged(mDispatchedSystemBarAppearance); } } - final boolean wasReportNextDraw = mReportNextDraw; - boolean useBlastSync = mNextDrawUseBlastSync; if (mFirst || windowShouldResize || viewVisibilityChanged || params != null || mForceNextWindowRelayout) { @@ -2896,19 +2924,13 @@ public final class ViewRootImpl implements ViewParent, mViewFrameInfo.flags |= FrameInfo.FLAG_WINDOW_VISIBILITY_CHANGED; } relayoutResult = relayoutWindow(params, viewVisibility, insetsPending); - final boolean freeformResizing = (relayoutResult - & RELAYOUT_RES_DRAG_RESIZING_FREEFORM) != 0; - final boolean dockedResizing = (relayoutResult - & RELAYOUT_RES_DRAG_RESIZING_DOCKED) != 0; - final boolean dragResizing = freeformResizing || dockedResizing; - if ((relayoutResult & WindowManagerGlobal.RELAYOUT_RES_BLAST_SYNC) != 0) { + final boolean dragResizing = mPendingDragResizing; + if (mSyncSeqId > mLastSyncSeqId) { + mLastSyncSeqId = mSyncSeqId; if (DEBUG_BLAST) { Log.d(mTag, "Relayout called with blastSync"); } reportNextDraw(); - if (isHardwareEnabled()) { - useBlastSync = true; - } } final boolean surfaceControlChanged = @@ -3043,9 +3065,6 @@ public final class ViewRootImpl implements ViewParent, if (mDragResizing != dragResizing) { if (dragResizing) { - mResizeMode = freeformResizing - ? RESIZE_MODE_FREEFORM - : RESIZE_MODE_DOCKED_DIVIDER; final boolean backdropSizeMatchesFrame = mWinFrame.width() == mPendingBackDropFrame.width() && mWinFrame.height() == mPendingBackDropFrame.height(); @@ -3147,12 +3166,9 @@ public final class ViewRootImpl implements ViewParent, // 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 +3235,7 @@ public final class ViewRootImpl implements ViewParent, prepareSurfaces(); } - final boolean didLayout = layoutRequested && (!mStopped || wasReportNextDraw); + final boolean didLayout = layoutRequested && (!mStopped || mReportNextDraw); boolean triggerGlobalLayoutListener = didLayout || mAttachInfo.mRecomputeGlobalAttributes; if (didLayout) { @@ -3412,51 +3428,40 @@ public final class ViewRootImpl implements ViewParent, 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).startChangingAnimations(); + mPendingTransitions.get(i).endChangingAnimations(); } 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; + 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(); } if (mAttachInfo.mContentCaptureEvents != null) { @@ -3465,6 +3470,46 @@ public final class ViewRootImpl implements ViewParent, 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 +4123,13 @@ public final class ViewRootImpl implements ViewParent, } } - /** - * 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 +4145,14 @@ public final class ViewRootImpl implements ViewParent, 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 +4183,81 @@ public final class ViewRootImpl implements ViewParent, }); } - 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() { - @Override - public void onFrameDraw(long frame) { - } + registerRtFrameCallback((frame) -> mBlurRegionAggregator + .dispatchBlurTransactionIfNeeded(frame, blurRegionsForFrame, hasBlurUpdates)); + } + private void registerCallbackForPendingTransactions() { + registerRtFrameCallback(new FrameDrawingCallback() { @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()); - } + mBlastBufferQueue.applyPendingTransactions(frame); 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); - } + return didProduceBuffer -> { + if (!didProduceBuffer) { + mBlastBufferQueue.applyPendingTransactions(frame); + } + }; - if (reportNextDraw) { - pendingDrawFinished(); - } - }); - }); - } + } - return createFrameCommitCallbackForSync(useBlastSync, reportNextDraw, - blastSyncConsumer); + @Override + public void onFrameDraw(long frame) { } - }; + }); } - 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 +4275,6 @@ public final class ViewRootImpl implements ViewParent, } if (mReportNextDraw) { - mReportNextDraw = false; // if we're using multi-thread renderer, wait for the window frame draws if (mWindowDrawCountDown != null) { @@ -4394,7 +4295,11 @@ public final class ViewRootImpl implements ViewParent, } 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 +4307,11 @@ public final class ViewRootImpl implements ViewParent, if (mAttachInfo.mThreadedRenderer != null) { mAttachInfo.mThreadedRenderer.fence(); } - pendingDrawFinished(); } } + if (mSyncBufferCallback != null && !usingAsyncReport) { + mSyncBufferCallback.onBufferReady(null); + } if (mPerformContentCapture) { performContentCaptureInitialReport(); } @@ -5413,7 +5320,6 @@ public final class ViewRootImpl implements ViewParent, 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 +5382,6 @@ public final class ViewRootImpl implements ViewParent, 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 +5614,6 @@ public final class ViewRootImpl implements ViewParent, final boolean hasCapture = msg.arg1 != 0; handlePointerCaptureChanged(hasCapture); } break; - case MSG_DRAW_FINISHED: { - pendingDrawFinished(); - } break; case MSG_SYSTEM_GESTURE_EXCLUSION_CHANGED: { systemGestureExclusionChanged(); } break; @@ -8071,17 +7972,16 @@ public final class ViewRootImpl implements ViewParent, 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); final WindowConfiguration winConfig = getConfiguration().windowConfiguration; - final boolean dragResizing = (relayoutResult - & (RELAYOUT_RES_DRAG_RESIZING_DOCKED | RELAYOUT_RES_DRAG_RESIZING_FREEFORM)) != 0; WindowLayout.computeSurfaceSize(mWindowAttributes, winConfig.getMaxBounds(), requestedWidth, - requestedHeight, mTmpFrames.frame, dragResizing, mSurfaceSize); - + requestedHeight, mTmpFrames.frame, mPendingDragResizing, mSurfaceSize); + final boolean transformHintChanged = transformHint != mLastTransformHint; final boolean sizeChanged = !mLastSurfaceSize.equals(mSurfaceSize); final boolean surfaceControlChanged = @@ -8497,7 +8397,7 @@ public final class ViewRootImpl implements ViewParent, 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 +8471,7 @@ public final class ViewRootImpl implements ViewParent, @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, int resizeMode) { final Rect frame = frames.frame; final Rect backDropFrame = frames.backdropFrame; if (DEBUG_LAYOUT) Log.v(mTag, "Resizing " + this + ": frame=" + frame.toShortString() @@ -8602,6 +8502,8 @@ public final class ViewRootImpl implements ViewParent, args.argi1 = forceLayout ? 1 : 0; args.argi2 = alwaysConsumeSystemBars ? 1 : 0; args.argi3 = displayId; + args.argi4 = seqId; + args.argi5 = resizeMode; msg.obj = args; mHandler.sendMessage(msg); } @@ -9893,8 +9795,8 @@ public final class ViewRootImpl implements ViewParent, } private void reportNextDraw() { - if (mReportNextDraw == false) { - drawPending(); + if (DEBUG_BLAST) { + Log.d(mTag, "reportNextDraw " + Debug.getCallers(5)); } mReportNextDraw = true; } @@ -9905,9 +9807,14 @@ public final class ViewRootImpl implements ViewParent, * 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 +9893,11 @@ public final class ViewRootImpl implements ViewParent, @Override public void resized(ClientWindowFrames frames, boolean reportDraw, MergedConfiguration mergedConfiguration, boolean forceLayout, - boolean alwaysConsumeSystemBars, int displayId) { + boolean alwaysConsumeSystemBars, int displayId, int seqId, int resizeMode) { final ViewRootImpl viewAncestor = mViewAncestor.get(); if (viewAncestor != null) { viewAncestor.dispatchResized(frames, reportDraw, mergedConfiguration, forceLayout, - alwaysConsumeSystemBars, displayId); + alwaysConsumeSystemBars, displayId, seqId, resizeMode); } } @@ -10908,7 +10815,7 @@ public final class ViewRootImpl implements ViewParent, } }; mOnBackInvokedDispatcher.registerOnBackInvokedCallback( - mCompatOnBackInvokedCallback, OnBackInvokedDispatcher.PRIORITY_DEFAULT); + OnBackInvokedDispatcher.PRIORITY_DEFAULT, mCompatOnBackInvokedCallback); } private void unregisterCompatOnBackInvokedCallback() { @@ -10933,14 +10840,15 @@ public final class ViewRootImpl implements ViewParent, 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 +10877,9 @@ public final class ViewRootImpl implements ViewParent, 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 +10893,40 @@ public final class ViewRootImpl implements ViewParent, // 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/WindowCallbacks.java b/core/java/android/view/WindowCallbacks.java index a99730205136..a7f0ef0a0324 100644 --- a/core/java/android/view/WindowCallbacks.java +++ b/core/java/android/view/WindowCallbacks.java @@ -28,9 +28,21 @@ import android.graphics.Rect; */ public interface WindowCallbacks { - public static final int RESIZE_MODE_INVALID = -1; - public static final int RESIZE_MODE_FREEFORM = 0; - public static final int RESIZE_MODE_DOCKED_DIVIDER = 1; + int RESIZE_MODE_INVALID = -1; + + /** + * 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)). + */ + int RESIZE_MODE_FREEFORM = 0; + + /** + * 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}. + */ + int RESIZE_MODE_DOCKED_DIVIDER = 1; /** * Called by the system when the window got changed by the user, before the layouter got called. diff --git a/core/java/android/view/WindowLayout.java b/core/java/android/view/WindowLayout.java index ad9f21b4fa70..a3b1313202c2 100644 --- a/core/java/android/view/WindowLayout.java +++ b/core/java/android/view/WindowLayout.java @@ -42,6 +42,7 @@ import android.graphics.Insets; import android.graphics.Point; import android.graphics.Rect; import android.util.Log; +import android.window.ClientWindowFrames; /** * Computes window frames. @@ -56,15 +57,17 @@ public class WindowLayout { 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 @@ public class WindowLayout { 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 @@ public class WindowLayout { 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 @@ public class WindowLayout { } 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 @@ public class WindowLayout { + " 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 2dc5fbd5439f..29a9926aeb9f 100644 --- a/core/java/android/view/WindowManagerGlobal.java +++ b/core/java/android/view/WindowManagerGlobal.java @@ -60,55 +60,27 @@ public final class WindowManagerGlobal { 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; - - /** - * 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; - - /** - * 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_SURFACE_CHANGED = 1 << 1; /** * 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 << 2; /** * 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 << 3; /** * 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 a270c9283ddc..06588b2cbb6d 100644 --- a/core/java/android/view/WindowlessWindowManager.java +++ b/core/java/android/view/WindowlessWindowManager.java @@ -22,6 +22,7 @@ import android.graphics.PixelFormat; 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 @@ public class WindowlessWindowManager implements IWindowSession { 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 @@ public class WindowlessWindowManager implements IWindowSession { 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 @@ public class WindowlessWindowManager implements IWindowSession { 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 @@ public class WindowlessWindowManager implements IWindowSession { @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 a8cc114c4d69..2c81eb1ae306 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 @@ public final class AutofillManager { return; } - int flags = FLAG_ACTIVITY_START; + int flags = FLAG_SUPPORTS_FILL_DIALOG; flags |= FLAG_VIEW_NOT_FOCUSED; notifyViewEntered(view, flags); } @@ -3121,17 +3121,19 @@ public final class AutofillManager { } /** - * 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/view/translation/UiTranslationManager.java b/core/java/android/view/translation/UiTranslationManager.java index 3012e9344a1b..01acdfec6c27 100644 --- a/core/java/android/view/translation/UiTranslationManager.java +++ b/core/java/android/view/translation/UiTranslationManager.java @@ -101,33 +101,32 @@ public final class UiTranslationManager { public static final String LOG_TAG = "UiTranslation"; /** - * The state caller request to disable utranslation,, it is no longer need to ui translation. + * The state the caller requests to enable UI translation. * * @hide */ public static final int STATE_UI_TRANSLATION_STARTED = 0; /** - * The state caller request to pause ui translation, it will switch back to the original text. + * The state caller requests to pause UI translation. It will switch back to the original text. * * @hide */ public static final int STATE_UI_TRANSLATION_PAUSED = 1; /** - * The state caller request to resume the paused ui translation, it will show the translated + * The state caller requests to resume the paused UI translation. It will show the translated * text again if the text had been translated. * * @hide */ public static final int STATE_UI_TRANSLATION_RESUMED = 2; /** - * The state the caller request to enable ui translation. + * The state caller requests to disable UI translation when it no longer needs translation. * * @hide */ public static final int STATE_UI_TRANSLATION_FINISHED = 3; - /** - * @hide - */ + + /** @hide */ @IntDef(prefix = {"STATE__TRANSLATION"}, value = { STATE_UI_TRANSLATION_STARTED, STATE_UI_TRANSLATION_PAUSED, @@ -145,6 +144,8 @@ public final class UiTranslationManager { public static final String EXTRA_SOURCE_LOCALE = "source_locale"; /** @hide */ public static final String EXTRA_TARGET_LOCALE = "target_locale"; + /** @hide */ + public static final String EXTRA_PACKAGE_NAME = "package_name"; @NonNull private final Context mContext; @@ -215,7 +216,7 @@ public final class UiTranslationManager { /** * Request to disable the ui translation. It will destroy all the {@link Translator}s and no - * longer to show to show the translated text. + * longer to show the translated text. * * @param activityId the identifier for the Activity which needs ui translation * @throws NullPointerException the activityId or @@ -362,8 +363,8 @@ public final class UiTranslationManager { public void onTranslationFinished(boolean activityDestroyed, ActivityId activityId, ComponentName componentName) { try { - mService.onTranslationFinished(activityDestroyed, - activityId.getToken(), componentName, mContext.getUserId()); + mService.onTranslationFinished(activityDestroyed, activityId.getToken(), componentName, + mContext.getUserId()); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } @@ -392,20 +393,21 @@ public final class UiTranslationManager { private void onStateChange(Bundle bundle) { int state = bundle.getInt(EXTRA_STATE); + String packageName = bundle.getString(EXTRA_PACKAGE_NAME); switch (state) { case STATE_UI_TRANSLATION_STARTED: - mSourceLocale = (ULocale) bundle.getSerializable(EXTRA_SOURCE_LOCALE); - mTargetLocale = (ULocale) bundle.getSerializable(EXTRA_TARGET_LOCALE); - mCallback.onStarted(mSourceLocale, mTargetLocale); + mSourceLocale = bundle.getSerializable(EXTRA_SOURCE_LOCALE, ULocale.class); + mTargetLocale = bundle.getSerializable(EXTRA_TARGET_LOCALE, ULocale.class); + mCallback.onStarted(mSourceLocale, mTargetLocale, packageName); break; case STATE_UI_TRANSLATION_RESUMED: - mCallback.onResumed(mSourceLocale, mTargetLocale); + mCallback.onResumed(mSourceLocale, mTargetLocale, packageName); break; case STATE_UI_TRANSLATION_PAUSED: - mCallback.onPaused(); + mCallback.onPaused(packageName); break; case STATE_UI_TRANSLATION_FINISHED: - mCallback.onFinished(); + mCallback.onFinished(packageName); break; default: Log.wtf(TAG, "Unexpected translation state:" + state); diff --git a/core/java/android/view/translation/UiTranslationStateCallback.java b/core/java/android/view/translation/UiTranslationStateCallback.java index d7dc284a2a09..3ccca5f5290f 100644 --- a/core/java/android/view/translation/UiTranslationStateCallback.java +++ b/core/java/android/view/translation/UiTranslationStateCallback.java @@ -24,11 +24,21 @@ import java.util.concurrent.Executor; /** * Callback for listening to UI Translation state changes. See {@link * UiTranslationManager#registerUiTranslationStateCallback(Executor, UiTranslationStateCallback)}. + * <p> + * Prior to Android version {@link android.os.Build.VERSION_CODES#TIRAMISU}, callback methods + * <em>without</em> {@code packageName} are invoked. Apps with minSdkVersion lower than {@link + * android.os.Build.VERSION_CODES#TIRAMISU} <em>must</em> implement those methods if they want to + * handle the events. + * <p> + * In Android version {@link android.os.Build.VERSION_CODES#TIRAMISU} and later, if both methods + * with and without {@code packageName} are implemented (e.g., {@link #onFinished()} and {@link + * #onFinished(String)}, only the one <em>with</em> {@code packageName} will be called. */ public interface UiTranslationStateCallback { /** - * @removed use {@link #onStarted(ULocale, ULocale)} instead. + * @removed use {@link #onStarted(ULocale, ULocale)} or {@link #onStarted(ULocale, ULocale, + * String)} instead. */ @Deprecated default void onStarted(@NonNull String sourceLocale, @NonNull String targetLocale) { @@ -41,27 +51,122 @@ public interface UiTranslationStateCallback { * <p> * This is also called if either the requested {@code sourceLocale} or {@code targetLocale} has * changed. + * <p> + * Apps should implement {@link #onStarted(ULocale, ULocale, String)} instead if they need the + * name of the package that owns the activity being translated. + * <p> + * Apps with minSdkVersion lower than {@link android.os.Build.VERSION_CODES#TIRAMISU} + * <em>must</em> implement this method if they want to handle the "started" event. + * + * @param sourceLocale {@link ULocale} the UI is being translated from. + * @param targetLocale {@link ULocale} the UI is being translated to. */ default void onStarted(@NonNull ULocale sourceLocale, @NonNull ULocale targetLocale) { onStarted(sourceLocale.getLanguage(), targetLocale.getLanguage()); } /** + * The system is requesting translation of the UI from {@code sourceLocale} to {@code + * targetLocale}. + * <p> + * This is also called if either the requested {@code sourceLocale} or {@code targetLocale} has + * changed. + * <p> + * Apps <em>may</em> implement {@link #onStarted(ULocale, ULocale)} instead if they don't need + * the name of the package that owns the activity being translated. + * <p> + * Apps with minSdkVersion lower than {@link android.os.Build.VERSION_CODES#TIRAMISU} + * <em>must</em> implement {@link #onStarted(ULocale, ULocale)} if they want to handle the + * "started" event. + * + * @param sourceLocale {@link ULocale} the UI is being translated from. + * @param targetLocale {@link ULocale} the UI is being translated to. + * @param packageName The name of the package that owns the activity being translated. + */ + default void onStarted(@NonNull ULocale sourceLocale, @NonNull ULocale targetLocale, + @NonNull String packageName) { + onStarted(sourceLocale, targetLocale); + } + + /** * The system is requesting that the application temporarily show the UI contents in their * original language. + * <p> + * Apps should implement {@link #onPaused(String)} as well if they need the name of the + * package that owns the activity being translated. */ void onPaused(); /** + * The system is requesting that the application temporarily show the UI contents in their + * original language. + * <p> + * Apps <em>may</em> implement {@link #onPaused()} instead if they don't need the name of the + * package that owns the activity being translated. + * <p> + * Apps with minSdkVersion lower than {@link android.os.Build.VERSION_CODES#TIRAMISU} + * <em>must</em> implement {@link #onPaused()} if they want to handle the "paused" event. + */ + default void onPaused(@NonNull String packageName) { + onPaused(); + } + + /** * The system is requesting that the application restore from the temporarily paused state and - * show the content in translated language. + * show the content in the translated language. + * <p> + * Apps should implement {@link #onResumed(ULocale, ULocale, String)} instead if they need the + * name of the package that owns the activity being translated. + * <p> + * Apps with minSdkVersion lower than {@link android.os.Build.VERSION_CODES#TIRAMISU} + * <em>must</em> implement this method if they want to handle the "resumed" event. + * + * @param sourceLocale {@link ULocale} the UI is being translated from. + * @param targetLocale {@link ULocale} the UI is being translated to. */ - // TODO: Remove the default implementation when clients have implemented this. default void onResumed(@NonNull ULocale sourceLocale, @NonNull ULocale targetLocale) { } /** + * The system is requesting that the application restore from the temporarily paused state and + * show the content in the translated language. + * <p> + * Apps <em>may</em> implement {@link #onResumed(ULocale, ULocale)} instead if they don't need + * the name of the package that owns the activity being translated. + * <p> + * Apps with minSdkVersion lower than {@link android.os.Build.VERSION_CODES#TIRAMISU} + * <em>must</em> implement {@link #onResumed(ULocale, ULocale)} if they want to handle the + * "resumed" event. + * + * @param sourceLocale {@link ULocale} the UI is being translated from. + * @param targetLocale {@link ULocale} the UI is being translated to. + * @param packageName The name of the package that owns the activity being translated. + */ + default void onResumed(@NonNull ULocale sourceLocale, @NonNull ULocale targetLocale, + @NonNull String packageName) { + onResumed(sourceLocale, targetLocale); + } + + /** * The UI Translation session has ended. + * <p> + * Apps should implement {@link #onFinished(String)} as well if they need the name of the + * package that owns the activity being translated. */ void onFinished(); + + /** + * The UI Translation session has ended. + * <p> + * Apps <em>may</em> implement {@link #onFinished()} instead if they don't need the name of the + * package that owns the activity being translated. + * <p> + * Apps with minSdkVersion lower than {@link android.os.Build.VERSION_CODES#TIRAMISU} + * <em>must</em> implement {@link #onFinished()} if they want to handle the "finished" event. + * + * @param packageName The name of the package that owns the activity being translated. + */ + default void onFinished(@NonNull String packageName) { + onFinished(); + } } diff --git a/core/java/android/view/translation/ViewTranslationCallback.java b/core/java/android/view/translation/ViewTranslationCallback.java index 66c028b48dc6..3936b639592d 100644 --- a/core/java/android/view/translation/ViewTranslationCallback.java +++ b/core/java/android/view/translation/ViewTranslationCallback.java @@ -60,7 +60,7 @@ public interface ViewTranslationCallback { /** * Called when user wants to view the original content instead of the translated content. This * method will not be called before {@link View#onViewTranslationResponse} or - * {@link View#onViewTranslationResponse}. + * {@link View#onVirtualViewTranslationResponses}. * * @return {@code true} if the View handles hiding the translation. */ diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java index b076d399d44a..3c8fcb978fbd 100644 --- a/core/java/android/widget/TextView.java +++ b/core/java/android/widget/TextView.java @@ -788,7 +788,8 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener 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 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener 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 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener @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 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener } /** - * 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; + public void setLineBreakStyle(@LineBreakConfig.LineBreakStyle int lineBreakStyle) { + if (mLineBreakStyle != lineBreakStyle) { + mLineBreakStyle = lineBreakStyle; + if (mLayout != null) { + nullLayouts(); + requestLayout(); + invalidate(); + } } - mLineBreakConfig.set(lineBreakConfig); - if (mLayout != null) { - nullLayouts(); - requestLayout(); - invalidate(); + } + + /** + * Set the line break word style 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 void setLineBreakWordStyle(@LineBreakConfig.LineBreakWordStyle int lineBreakWordStyle) { + if (mLineBreakWordStyle != lineBreakWordStyle) { + mLineBreakWordStyle = lineBreakWordStyle; + if (mLayout != null) { + nullLayouts(); + requestLayout(); + invalidate(); + } } } /** - * Get the current line break configuration for text wrapping. + * Get the current line break style for text wrapping. * - * @return the current line break configuration to be used for text wrapping. + * @return the current line break style to be used for text wrapping. */ - public @NonNull LineBreakConfig getLineBreakConfig() { - LineBreakConfig lbConfig = new LineBreakConfig(); - lbConfig.set(mLineBreakConfig); - return lbConfig; + 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 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener * @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 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener 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 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener } 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 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener .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 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener .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 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener .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 acf9882e6658..5b915cc22ec5 100644 --- a/core/java/android/window/ClientWindowFrames.java +++ b/core/java/android/window/ClientWindowFrames.java @@ -27,47 +27,55 @@ import android.os.Parcelable; */ 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 @@ public class ClientWindowFrames implements Parcelable { 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 dcd80fd76e09..400a56f2c485 100644 --- a/core/java/android/window/OnBackInvokedCallback.java +++ b/core/java/android/window/OnBackInvokedCallback.java @@ -33,7 +33,7 @@ import android.view.View; * 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 63e6d30c8c0b..5eed8cde8c7c 100644 --- a/core/java/android/window/OnBackInvokedDispatcher.java +++ b/core/java/android/window/OnBackInvokedDispatcher.java @@ -94,15 +94,15 @@ public interface OnBackInvokedDispatcher { * 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 cf17a2116aac..2b2f5e945710 100644 --- a/core/java/android/window/ProxyOnBackInvokedDispatcher.java +++ b/core/java/android/window/ProxyOnBackInvokedDispatcher.java @@ -44,7 +44,7 @@ public class ProxyOnBackInvokedDispatcher implements OnBackInvokedDispatcher { /** * 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 @@ public class ProxyOnBackInvokedDispatcher implements OnBackInvokedDispatcher { @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 @@ public class ProxyOnBackInvokedDispatcher implements OnBackInvokedDispatcher { mCallbacks.add(Pair.create(callback, priority)); if (mActualDispatcherOwner != null) { mActualDispatcherOwner.getOnBackInvokedDispatcher().registerOnBackInvokedCallback( - callback, priority); + priority, callback); } } } @@ -115,7 +115,7 @@ public class ProxyOnBackInvokedDispatcher implements OnBackInvokedDispatcher { 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/SplashScreen.java b/core/java/android/window/SplashScreen.java index fab180dae0bf..f1c0d8dee525 100644 --- a/core/java/android/window/SplashScreen.java +++ b/core/java/android/window/SplashScreen.java @@ -100,8 +100,12 @@ public interface SplashScreen { * <p> * To reset to the default theme, set this the themeId to {@link Resources#ID_NULL}. * <p> - * <b>Note:</b> The theme name must be stable across versions, otherwise it won't be found - * after your application is updated. + * <b>Note:</b> Internally, the theme name is resolved and persisted. This means that the theme + * name must be stable across versions, otherwise it won't be found after your application is + * updated. + * + * @param themeId The ID of the splashscreen theme to be used in place of the one defined in + * the manifest. */ void setSplashScreenTheme(@StyleRes int themeId); diff --git a/core/java/android/window/WindowInfosListener.java b/core/java/android/window/WindowInfosListener.java index 9d4545c6e25d..8db5a5eb0e47 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 @@ public abstract class WindowInfosListener { /** * 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 @@ public abstract class WindowInfosListener { } 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 5dbb551da681..97573c291340 100644 --- a/core/java/android/window/WindowOnBackInvokedDispatcher.java +++ b/core/java/android/window/WindowOnBackInvokedDispatcher.java @@ -53,7 +53,7 @@ public class WindowOnBackInvokedDispatcher implements OnBackInvokedDispatcher { 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 @@ public class WindowOnBackInvokedDispatcher implements OnBackInvokedDispatcher { // 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 393bff483a20..916408984674 100644 --- a/core/java/com/android/internal/app/ChooserMultiProfilePagerAdapter.java +++ b/core/java/com/android/internal/app/ChooserMultiProfilePagerAdapter.java @@ -247,54 +247,54 @@ public class ChooserMultiProfilePagerAdapter extends AbstractMultiProfilePagerAd } 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 25b8dba2870b..6e7690678d21 100644 --- a/core/java/com/android/internal/app/IntentForwarderActivity.java +++ b/core/java/com/android/internal/app/IntentForwarderActivity.java @@ -163,13 +163,13 @@ public class IntentForwarderActivity extends Activity { } 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 fd5eac8071bd..5ebb148760c6 100644 --- a/core/java/com/android/internal/app/ResolverActivity.java +++ b/core/java/com/android/internal/app/ResolverActivity.java @@ -850,13 +850,13 @@ public class ResolverActivity extends Activity implements } 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 @@ public class ResolverActivity extends Activity implements } 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 @@ public class ResolverActivity extends Activity implements } 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 @@ public class ResolverActivity extends Activity implements } 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 4da59a3e77d9..f4e568b6676a 100644 --- a/core/java/com/android/internal/app/ResolverMultiProfilePagerAdapter.java +++ b/core/java/com/android/internal/app/ResolverMultiProfilePagerAdapter.java @@ -242,40 +242,40 @@ public class ResolverMultiProfilePagerAdapter extends AbstractMultiProfilePagerA } 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 3531fad353db..957a6365739d 100644 --- a/core/java/com/android/internal/app/UnlaunchableAppActivity.java +++ b/core/java/com/android/internal/app/UnlaunchableAppActivity.java @@ -95,12 +95,12 @@ public class UnlaunchableAppActivity extends Activity } 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 9e07f973b3c4..cb162674eb16 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.Looper; 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 @@ public interface ServiceConnector<I extends IInterface> { 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 34c47ede99f0..06bc4b56901a 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.annotation.Nullable; 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 @@ public class FrameTracker extends SurfaceControl.OnJankDataListener if (mBeginVsyncId != INVALID_ID) { mSurfaceControlWrapper.addJankStatsListener( FrameTracker.this, mSurfaceControl); + markEvent("FT#deferMonitoring"); postTraceStartMarker(); } } @@ -241,8 +243,9 @@ public class FrameTracker extends SurfaceControl.OnJankDataListener } 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 @@ public class FrameTracker extends SurfaceControl.OnJankDataListener return; } mTracingStarted = true; + markEvent("FT#begin"); Trace.beginAsyncSection(mSession.getName(), (int) mBeginVsyncId); } } @@ -295,6 +299,7 @@ public class FrameTracker extends SurfaceControl.OnJankDataListener 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 @@ public class FrameTracker extends SurfaceControl.OnJankDataListener 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 @@ public class FrameTracker extends SurfaceControl.OnJankDataListener } } + 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 c90d851201a2..000000000000 --- 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 34643105b965..000000000000 --- 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/UiEventLogger.java b/core/java/com/android/internal/logging/UiEventLogger.java deleted file mode 100644 index 5378b03fe1c5..000000000000 --- 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 b79c0bed4564..a93c487db7d7 100644 --- a/core/java/com/android/internal/notification/SystemNotificationChannels.java +++ b/core/java/com/android/internal/notification/SystemNotificationChannels.java @@ -221,7 +221,7 @@ public class SystemNotificationChannels { 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 52539566351b..8901c0774783 100644 --- a/core/java/com/android/internal/os/BatteryStatsImpl.java +++ b/core/java/com/android/internal/os/BatteryStatsImpl.java @@ -166,7 +166,7 @@ public class BatteryStatsImpl extends BatteryStats { 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 @@ public class BatteryStatsImpl extends BatteryStats { * 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,16 +1034,199 @@ public class BatteryStatsImpl extends BatteryStats { } /** - * 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,20 +2122,28 @@ public class BatteryStatsImpl extends BatteryStats { private final TimeBase mTimeBase; private final LongMultiStateCounter mCounter; - private TimeMultiStateCounter(TimeBase timeBase, Parcel in, long timestampMs) { - mTimeBase = timeBase; - mCounter = LongMultiStateCounter.CREATOR.createFromParcel(in); - mCounter.setEnabled(mTimeBase.isRunning(), timestampMs); - timeBase.add(this); + private TimeMultiStateCounter(TimeBase timeBase, int stateCount, long timestampMs) { + this(timeBase, new LongMultiStateCounter(stateCount), timestampMs); } - private TimeMultiStateCounter(TimeBase timeBase, int stateCount, long timestampMs) { + private TimeMultiStateCounter(TimeBase timeBase, LongMultiStateCounter counter, + long timestampMs) { mTimeBase = timeBase; - mCounter = new LongMultiStateCounter(stateCount); + mCounter = counter; 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) { mCounter.writeToParcel(out, 0); } @@ -3510,11 +3711,8 @@ public class BatteryStatsImpl extends BatteryStats { 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 @@ public class BatteryStatsImpl extends BatteryStats { // 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 @@ public class BatteryStatsImpl extends BatteryStats { 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 @@ public class BatteryStatsImpl extends BatteryStats { 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 @@ public class BatteryStatsImpl extends BatteryStats { 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 @@ public class BatteryStatsImpl extends BatteryStats { @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 @@ public class BatteryStatsImpl extends BatteryStats { 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 @@ public class BatteryStatsImpl extends BatteryStats { } 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 @@ public class BatteryStatsImpl extends BatteryStats { @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 @@ public class BatteryStatsImpl extends BatteryStats { @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 @@ public class BatteryStatsImpl extends BatteryStats { .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 @@ public class BatteryStatsImpl extends BatteryStats { 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 @@ public class BatteryStatsImpl extends BatteryStats { = 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 @@ public class BatteryStatsImpl extends BatteryStats { 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 @@ public class BatteryStatsImpl extends BatteryStats { 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 @@ public class BatteryStatsImpl extends BatteryStats { 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 @@ public class BatteryStatsImpl extends BatteryStats { 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 @@ public class BatteryStatsImpl extends BatteryStats { 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 @@ public class BatteryStatsImpl extends BatteryStats { 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 @@ public class BatteryStatsImpl extends BatteryStats { 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 @@ public class BatteryStatsImpl extends BatteryStats { 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 @@ public class BatteryStatsImpl extends BatteryStats { 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 1c3f8b0bf095..58d51e327ade 100644 --- a/core/java/com/android/internal/os/KernelAllocationStats.java +++ b/core/java/com/android/internal/os/KernelAllocationStats.java @@ -24,21 +24,29 @@ public final class KernelAllocationStats { /** 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 @@ public final class KernelAllocationStats { * 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 7262e846d9b0..7fb8696a217d 100644 --- a/core/java/com/android/internal/power/MeasuredEnergyStats.java +++ b/core/java/com/android/internal/power/MeasuredEnergyStats.java @@ -194,6 +194,7 @@ public class MeasuredEnergyStats { return mSupportedMultiStateBuckets[index]; } + @NonNull public String[] getStateNames() { return mStateNames; } @@ -321,6 +322,10 @@ public class MeasuredEnergyStats { 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 1cd758c0f43b..3f7c4d53d333 100644 --- a/core/java/com/android/internal/util/LatencyTracker.java +++ b/core/java/com/android/internal/util/LatencyTracker.java @@ -132,6 +132,11 @@ public class LatencyTracker { */ 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 @@ public class LatencyTracker { 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 @@ public class LatencyTracker { 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 @@ public class LatencyTracker { 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 @@ public class LatencyTracker { 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 6673f6781ef8..52f0fb578e3d 100644 --- a/core/java/com/android/internal/view/BaseIWindow.java +++ b/core/java/com/android/internal/view/BaseIWindow.java @@ -51,10 +51,10 @@ public class BaseIWindow extends IWindow.Stub { @Override public void resized(ClientWindowFrames frames, boolean reportDraw, MergedConfiguration mergedConfiguration, boolean forceLayout, - boolean alwaysConsumeSystemBars, int displayId) { + boolean alwaysConsumeSystemBars, int displayId, int seqId, int resizeMode) { 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/ConversationLayout.java b/core/java/com/android/internal/widget/ConversationLayout.java index 5fa4a652e176..4706affa3541 100644 --- a/core/java/com/android/internal/widget/ConversationLayout.java +++ b/core/java/com/android/internal/widget/ConversationLayout.java @@ -66,7 +66,6 @@ import java.util.ArrayList; import java.util.List; import java.util.Map; import java.util.Objects; -import java.util.function.Consumer; /** * A custom-built layout for the Notification.MessagingStyle allows dynamic addition and removal @@ -76,8 +75,6 @@ import java.util.function.Consumer; public class ConversationLayout extends FrameLayout implements ImageMessageConsumer, IMessagingLayout { - private static final Consumer<MessagingMessage> REMOVE_MESSAGE - = MessagingMessage::removeMessage; public static final Interpolator LINEAR_OUT_SLOW_IN = new PathInterpolator(0f, 0f, 0.2f, 1f); public static final Interpolator FAST_OUT_LINEAR_IN = new PathInterpolator(0.4f, 0f, 1f, 1f); public static final Interpolator FAST_OUT_SLOW_IN = new PathInterpolator(0.4f, 0f, 0.2f, 1f); @@ -150,7 +147,7 @@ public class ConversationLayout extends FrameLayout private Icon mShortcutIcon; private View mAppNameDivider; private TouchDelegateComposite mTouchDelegate = new TouchDelegateComposite(this); - private ArrayList<MessagingGroup> mToRecycle = new ArrayList<>(); + private ArrayList<MessagingLinearLayout.MessagingChild> mToRecycle = new ArrayList<>(); public ConversationLayout(@NonNull Context context) { super(context); @@ -463,8 +460,12 @@ public class ConversationLayout extends FrameLayout removeGroups(oldGroups); // Let's remove the remaining messages - mMessages.forEach(REMOVE_MESSAGE); - mHistoricMessages.forEach(REMOVE_MESSAGE); + for (MessagingMessage message : mMessages) { + message.removeMessage(mToRecycle); + } + for (MessagingMessage historicMessage : mHistoricMessages) { + historicMessage.removeMessage(mToRecycle); + } mMessages = messages; mHistoricMessages = historicMessages; @@ -475,8 +476,8 @@ public class ConversationLayout extends FrameLayout updateConversationLayout(); // Recycle everything at the end of the update, now that we know it's no longer needed. - for (MessagingGroup group : mToRecycle) { - group.recycle(); + for (MessagingLinearLayout.MessagingChild child : mToRecycle) { + child.recycle(); } mToRecycle.clear(); } diff --git a/core/java/com/android/internal/widget/ILockSettings.aidl b/core/java/com/android/internal/widget/ILockSettings.aidl index 851e8e0f3269..3494c9e05b4a 100644 --- a/core/java/com/android/internal/widget/ILockSettings.aidl +++ b/core/java/com/android/internal/widget/ILockSettings.aidl @@ -53,7 +53,6 @@ interface ILockSettings { 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 521b2f6afa0f..a94b30707604 100644 --- a/core/java/com/android/internal/widget/LockPatternUtils.java +++ b/core/java/com/android/internal/widget/LockPatternUtils.java @@ -526,20 +526,6 @@ public class LockPatternUtils { } /** - * 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/internal/widget/MessagingGroup.java b/core/java/com/android/internal/widget/MessagingGroup.java index 9e06e33b79b5..146cb3fadaac 100644 --- a/core/java/com/android/internal/widget/MessagingGroup.java +++ b/core/java/com/android/internal/widget/MessagingGroup.java @@ -262,7 +262,8 @@ public class MessagingGroup extends LinearLayout implements MessagingLinearLayou return createdGroup; } - public void removeMessage(MessagingMessage messagingMessage) { + public void removeMessage(MessagingMessage messagingMessage, + ArrayList<MessagingLinearLayout.MessagingChild> toRecycle) { View view = messagingMessage.getView(); boolean wasShown = view.isShown(); ViewGroup messageParent = (ViewGroup) view.getParent(); @@ -270,15 +271,14 @@ public class MessagingGroup extends LinearLayout implements MessagingLinearLayou return; } messageParent.removeView(view); - Runnable recycleRunnable = () -> { - messageParent.removeTransientView(view); - messagingMessage.recycle(); - }; if (wasShown && !MessagingLinearLayout.isGone(view)) { messageParent.addTransientView(view, 0); - performRemoveAnimation(view, recycleRunnable); + performRemoveAnimation(view, () -> { + messageParent.removeTransientView(view); + messagingMessage.recycle(); + }); } else { - recycleRunnable.run(); + toRecycle.add(messagingMessage); } } diff --git a/core/java/com/android/internal/widget/MessagingLayout.java b/core/java/com/android/internal/widget/MessagingLayout.java index 21ca196886ab..9ac6ef77bc07 100644 --- a/core/java/com/android/internal/widget/MessagingLayout.java +++ b/core/java/com/android/internal/widget/MessagingLayout.java @@ -51,7 +51,6 @@ import com.android.internal.util.ContrastColorUtil; import java.util.ArrayList; import java.util.List; import java.util.Map; -import java.util.function.Consumer; /** * A custom-built layout for the Notification.MessagingStyle allows dynamic addition and removal @@ -62,8 +61,6 @@ public class MessagingLayout extends FrameLayout implements ImageMessageConsumer, IMessagingLayout { private static final float COLOR_SHIFT_AMOUNT = 60; - private static final Consumer<MessagingMessage> REMOVE_MESSAGE - = MessagingMessage::removeMessage; public static final Interpolator LINEAR_OUT_SLOW_IN = new PathInterpolator(0f, 0f, 0.2f, 1f); public static final Interpolator FAST_OUT_LINEAR_IN = new PathInterpolator(0.4f, 0f, 1f, 1f); public static final Interpolator FAST_OUT_SLOW_IN = new PathInterpolator(0.4f, 0f, 0.2f, 1f); @@ -89,6 +86,7 @@ public class MessagingLayout extends FrameLayout private boolean mIsCollapsed; private ImageResolver mImageResolver; private CharSequence mConversationTitle; + private ArrayList<MessagingLinearLayout.MessagingChild> mToRecycle = new ArrayList<>(); public MessagingLayout(@NonNull Context context) { super(context); @@ -212,8 +210,12 @@ public class MessagingLayout extends FrameLayout removeGroups(oldGroups); // Let's remove the remaining messages - mMessages.forEach(REMOVE_MESSAGE); - mHistoricMessages.forEach(REMOVE_MESSAGE); + for (MessagingMessage message : mMessages) { + message.removeMessage(mToRecycle); + } + for (MessagingMessage historicMessage : mHistoricMessages) { + historicMessage.removeMessage(mToRecycle); + } mMessages = messages; mHistoricMessages = historicMessages; @@ -223,6 +225,12 @@ public class MessagingLayout extends FrameLayout // after groups are finalized, hide the first sender name if it's showing as the title mPeopleHelper.maybeHideFirstSenderName(mGroups, mIsOneToOne, mConversationTitle); updateImageMessages(); + + // Recycle everything at the end of the update, now that we know it's no longer needed. + for (MessagingLinearLayout.MessagingChild child : mToRecycle) { + child.recycle(); + } + mToRecycle.clear(); } private void updateImageMessages() { @@ -263,18 +271,17 @@ public class MessagingLayout extends FrameLayout MessagingGroup group = oldGroups.get(i); if (!mGroups.contains(group)) { List<MessagingMessage> messages = group.getMessages(); - Runnable endRunnable = () -> { - mMessagingLinearLayout.removeTransientView(group); - group.recycle(); - }; boolean wasShown = group.isShown(); mMessagingLinearLayout.removeView(group); if (wasShown && !MessagingLinearLayout.isGone(group)) { mMessagingLinearLayout.addTransientView(group, 0); - group.removeGroupAnimated(endRunnable); + group.removeGroupAnimated(() -> { + mMessagingLinearLayout.removeTransientView(group); + group.recycle(); + }); } else { - endRunnable.run(); + mToRecycle.add(group); } mMessages.removeAll(messages); mHistoricMessages.removeAll(messages); diff --git a/core/java/com/android/internal/widget/MessagingLinearLayout.java b/core/java/com/android/internal/widget/MessagingLinearLayout.java index cb1d387dbd07..c06f5f75514f 100644 --- a/core/java/com/android/internal/widget/MessagingLinearLayout.java +++ b/core/java/com/android/internal/widget/MessagingLinearLayout.java @@ -365,6 +365,7 @@ public class MessagingLinearLayout extends ViewGroup { default int getExtraSpacing() { return 0; } + void recycle(); } public static class LayoutParams extends MarginLayoutParams { diff --git a/core/java/com/android/internal/widget/MessagingMessage.java b/core/java/com/android/internal/widget/MessagingMessage.java index 8c8437951402..2cc0d2305a78 100644 --- a/core/java/com/android/internal/widget/MessagingMessage.java +++ b/core/java/com/android/internal/widget/MessagingMessage.java @@ -20,6 +20,7 @@ import android.app.ActivityManager; import android.app.Notification; import android.view.View; +import java.util.ArrayList; import java.util.Objects; /** @@ -96,8 +97,8 @@ public interface MessagingMessage extends MessagingLinearLayout.MessagingChild { return sameAs(message.getMessage()); } - default void removeMessage() { - getGroup().removeMessage(this); + default void removeMessage(ArrayList<MessagingLinearLayout.MessagingChild> toRecycle) { + getGroup().removeMessage(this, toRecycle); } default void setMessagingGroup(MessagingGroup group) { diff --git a/core/java/com/android/server/SystemConfig.java b/core/java/com/android/server/SystemConfig.java index b1846d2402dd..db41d333e1d4 100644 --- a/core/java/com/android/server/SystemConfig.java +++ b/core/java/com/android/server/SystemConfig.java @@ -31,9 +31,11 @@ import android.os.FileUtils; 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.File; 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; @@ -435,15 +440,15 @@ public class SystemConfig { } /** Get privapp permission allowlist for an apk-in-apex. */ - public ArraySet<String> getApexPrivAppPermissions(String module, String packageName) { - return mApexPrivAppPermissions.getOrDefault(module, EMPTY_PERMISSIONS) - .get(packageName); + public ArraySet<String> getApexPrivAppPermissions(String apexName, String apkPackageName) { + return mApexPrivAppPermissions.getOrDefault(apexName, EMPTY_PERMISSIONS) + .get(apkPackageName); } /** Get privapp permissions denylist for an apk-in-apex. */ - public ArraySet<String> getApexPrivAppDenyPermissions(String module, String packageName) { - return mApexPrivAppDenyPermissions.getOrDefault(module, EMPTY_PERMISSIONS) - .get(packageName); + public ArraySet<String> getApexPrivAppDenyPermissions(String apexName, String apkPackageName) { + return mApexPrivAppDenyPermissions.getOrDefault(apexName, EMPTY_PERMISSIONS) + .get(apkPackageName); } public ArraySet<String> getVendorPrivAppPermissions(String packageName) { @@ -1187,7 +1192,8 @@ public class SystemConfig { 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 @@ public class SystemConfig { 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 @@ public class SystemConfig { 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 4aa00f6117b9..a1be88440c97 100644 --- a/core/jni/Android.bp +++ b/core/jni/Android.bp @@ -272,6 +272,7 @@ cc_library_shared { "libinput", "libcamera_client", "libcamera_metadata", + "libprocinfo", "libsqlite", "libEGL", "libGLESv1_CM", @@ -361,7 +362,7 @@ cc_library_shared { "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 68025a8ba0e4..39f192b662ee 100644 --- a/core/jni/android_view_SurfaceControl.cpp +++ b/core/jni/android_view_SurfaceControl.cpp @@ -253,6 +253,11 @@ static struct { jfieldID alphaInterpretation; } gDisplayDecorationSupportInfo; +static struct { + jclass clazz; + jmethodID invokeReleaseCallback; +} gInvokeReleaseCallback; + class JNamedColorSpace { public: // ColorSpace.Named.SRGB.ordinal() = 0; @@ -625,8 +630,59 @@ static void nativeSetGeometry(JNIEnv* env, jclass clazz, jlong transactionObj, j 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 @@ static void nativeSetBuffer(JNIEnv* env, jclass clazz, jlong transactionObj, jlo 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 @@ static const JNINativeMethod sSurfaceControlMethods[] = { (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 @@ int register_android_view_SurfaceControl(JNIEnv* env) 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 08c9f20b0815..aae2549df429 100644 --- a/core/jni/android_window_WindowInfosListener.cpp +++ b/core/jni/android_window_WindowInfosListener.cpp @@ -44,6 +44,11 @@ static struct { jmethodID ctor; } gDisplayInfoClassInfo; +static struct { + jclass clazz; + jmethodID ctor; +} gPairClassInfo; + static jclass gInputWindowHandleClass; jobject fromDisplayInfo(JNIEnv* env, gui::DisplayInfo displayInfo) { @@ -57,6 +62,30 @@ jobject fromDisplayInfo(JNIEnv* env, gui::DisplayInfo displayInfo) { 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 @@ struct WindowInfosListener : public gui::WindowInfosListener { 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 @@ void destroyNativeService(void* ptr) { 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 @@ static jlong nativeGetFinalizer(JNIEnv* /* env */, jclass /* clazz */) { 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 @@ int register_android_window_WindowInfosListener(JNIEnv* env) { 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 e0a24430e739..5b104977f1d8 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 @@ static jmethodID gProcessGpuMemCtor; 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(); + + // 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()); + } + inodeToSize[buf.inode()] = buf.size(); + } + + 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"; } - 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(); + + 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]; + } } - retainedSize /= 1024; + + 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 env->NewObject(gProcessDmabufClazz, gProcessDmabufCtor, retainedSize, retainedCount, - mappedSize, mappedCount); + + return ret; } static jobject KernelAllocationStats_getGpuAllocations(JNIEnv *env) { @@ -74,7 +178,7 @@ static jobject KernelAllocationStats_getGpuAllocations(JNIEnv *env) { } 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 @@ int register_com_android_internal_os_KernelAllocationStats(JNIEnv *env) { 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 @@ int register_com_android_internal_os_KernelAllocationStats(JNIEnv *env) { 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 000000000000..8769ebb74979 --- /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 cc90e05de744..856bc839aee5 100644 --- a/core/proto/android/os/batteryusagestats.proto +++ b/core/proto/android/os/batteryusagestats.proto @@ -76,6 +76,7 @@ message BatteryUsageStatsAtomsProto { 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 d652b2ff4f4a..45b6c786670d 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" @@ -6422,7 +6439,7 @@ <!-- Allows an UID to be visible to the application based on an interaction between the two apps. This permission is not intended to be held by apps. - @hide @TestApi --> + @hide @TestApi @SystemApi(client=android.annotation.SystemApi.Client.MODULE_LIBRARIES) --> <permission android:name="android.permission.MAKE_UID_VISIBLE" android:protectionLevel="signature" /> diff --git a/core/res/res/drawable-nodpi/stat_sys_adb.xml b/core/res/res/drawable-nodpi/stat_sys_adb.xml index f8c04517800a..cb4462c9a169 100644 --- a/core/res/res/drawable-nodpi/stat_sys_adb.xml +++ b/core/res/res/drawable-nodpi/stat_sys_adb.xml @@ -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,11 +13,78 @@ Copyright (C) 2021 The Android Open Source Project See the License for the specific language governing permissions and limitations under the License. --> -<vector xmlns:android="http://schemas.android.com/apk/res/android" - android:width="24dp" android:height="24dp" - android:viewportWidth="24" - android:viewportHeight="24"> - <path android:pathData="M18 9c0-.69268-.1174-1.35795-.3333-1.97699C16.8495 4.68061 14.621 3 12 3 8.68629 3 6 5.68629 6 9v3h6M6 15c0 .6927.11738 1.3579.33333 1.977C7.15047 19.3194 9.37897 21 12 21c3.3137 0 6-2.6863 6-6v-3h-6" android:strokeColor="#000000" android:strokeWidth="2" android:fillColor="#00000000"/> - <path android:fillColor="#000000" android:pathData="M10 7a1 1 0 1 0 0 2 1 1 0 1 0 0-2zM14 7a1 1 0 1 0 0 2 1 1 0 1 0 0-2z"/> - <path android:pathData="M6 3l1.5 1.5M18 3l-1.5 1.5" android:strokeColor="#000000" android:strokeWidth="2" android:fillColor="#000000"/> +<vector android:width="24dp" android:height="24dp" + android:viewportWidth="24" android:viewportHeight="24" + xmlns:android="http://schemas.android.com/apk/res/android"> + <path android:pathData=" + M22.45 11.94 + l-.58-.21 + a1.19 1.19 0 0 1-.26-2.12 + l.51-.34 + a1.2 1.2 0 0 0-.83-2.19 + l-.61.08 + a1.2 1.2 0 0 1-1.21-1.76 + l.29-.54 + A1.2 1.2 0 0 0 18 3.31 + l-.5.36 + a1.21 1.21 0 0 1-1.9-1 + v-.61 + a1.2 1.2 0 0 0-2.27-.56 + l-.26.5 + a1.2 1.2 0 0 1-2.14 0 + l-.28-.54 + a1.2 1.2 0 0 0-2.27.56 + v.61 + a1.21 1.21 0 0 1-1.9 1 + L6 3.31 + a1.2 1.2 0 0 0-1.76 1.55 + l.29.54 + a1.2 1.2 0 0 1-1.21 1.76 + l-.61-.08 + a1.2 1.2 0 0 0-.83 2.19 + l.51.34 + a1.19 1.19 0 0 1-.26 2.12 + l-.58.21 + a1.21 1.21 0 0 0 .29 2.33 + l.61.06 + a1.2 1.2 0 0 1 .76 2 + l-.42.46 + a1.2 1.2 0 0 0 1.33 1.92 + l.57-.22 + a1.21 1.21 0 0 1 1.61 1.42 + l-.16.59 + a1.2 1.2 0 0 0 2.07 1.09 + l.4-.47 + a1.2 1.2 0 0 1 2.08.51 + l.14.6 + a1.2 1.2 0 0 0 2.34 0 + l.14-.6 + a1.2 1.2 0 0 1 2.08-.51 + l.4.47 + a1.2 1.2 0 0 0 2.07-1.09 + l-.16-.59 + a1.21 1.21 0 0 1 1.61-1.42 + l.57.22 + a1.2 1.2 0 0 0 1.33-1.92 + l-.42-.46 + a1.2 1.2 0 0 1 .76-2 + l.61-.06 + a1.21 1.21 0 0 0 .29-2.33 + z + M12 19 + a7 7 0 1 1 7-7 7 7 0 0 1-7 7 + z + " + android:fillColor="#000000" /> + <path android:pathData=" + M9 7.75 + a.75.75 0 1 0 0 1.5.75.75 0 1 0 0-1.5 + z + M15 7.75 + a.75.75 0 1 0 0 1.5.75.75 0 1 0 0-1.5 + z + " + android:fillColor="#000000" /> + <path android:strokeColor="#000000" android:strokeMiterLimit="10" android:strokeWidth="2" + android:pathData="M4 12h16M12 12v8" /> </vector> diff --git a/core/res/res/values/attrs.xml b/core/res/res/values/attrs.xml index da5f8998d156..2107f651eade 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 579ef512e671..7562b9aa0ead 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 269aa1bb7729..1e4edfbe82d7 100644 --- a/core/res/res/values/config.xml +++ b/core/res/res/values/config.xml @@ -2963,6 +2963,11 @@ the currently focused view is a text editor. --> <bool name="config_preventImeStartupUnlessTextEditor">false</bool> + <!-- These IMEs are known not to behave well when evicted from memory and thus are exempt + from the IME startup prevention behavior that is enabled by + config_preventImeStartupUnlessTextEditor. --> + <string-array name="config_nonPreemptibleInputMethods" translatable="false" /> + <!-- The list of classes that should be added to the notification ranking pipeline. See {@link com.android.server.notification.NotificationSignalExtractor} If you add a new extractor to this list make sure to update @@ -4857,6 +4862,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 +5747,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 +5801,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 2dc17b8468c3..e35d2e9f488a 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/res/res/values/strings.xml b/core/res/res/values/strings.xml index 04a70cb67d8c..4c71b3abd00c 100644 --- a/core/res/res/values/strings.xml +++ b/core/res/res/values/strings.xml @@ -5739,7 +5739,7 @@ <!-- Content for the log access confirmation dialog. [CHAR LIMIT=NONE]--> <string name="log_access_confirmation_body">Device logs record what happens on your device. Apps can use these logs to find and fix issues.\n\nSome logs may contain sensitive info, so only allow apps you trust to access all device logs. - \n\nIf you don’t allow this app to access all device logs, it can still access its own logs, and your device manufacturer may still be able to access some logs or info on your device. Learn more + \n\nIf you don’t allow this app to access all device logs, it can still access its own logs and your device manufacturer may still be able to access some logs or info on your device. Learn more </string> <!-- Privacy notice do not show [CHAR LIMIT=20] --> diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml index 1f0b22b9e460..595433ecf523 100644 --- a/core/res/res/values/symbols.xml +++ b/core/res/res/values/symbols.xml @@ -2269,6 +2269,7 @@ <java-symbol type="string" name="config_notificationAccessConfirmationActivity" /> <java-symbol type="bool" name="config_killableInputMethods" /> <java-symbol type="bool" name="config_preventImeStartupUnlessTextEditor" /> + <java-symbol type="array" name="config_nonPreemptibleInputMethods" /> <java-symbol type="layout" name="resolver_list" /> <java-symbol type="id" name="resolver_list" /> 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 6a53f6843d48..19bb718578a0 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 @@ public class BatteryConsumerData { 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 23b12cf3ea4b..fd08e3c789f7 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 @@ public class BatteryUsageStatsPulledTest { 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 fa657f7a8928..5e076076d2f4 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.verify; 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 @@ public class CrossProfileAppsTest { @Mock private DevicePolicyManager mDevicePolicyManager; @Mock + private DevicePolicyResourcesManager mDevicePolicyResourcesManager; + @Mock private ICrossProfileApps mService; @Mock private Resources mResources; @@ -89,6 +92,7 @@ public class CrossProfileAppsTest { 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 @@ public class CrossProfileAppsTest { 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 @@ public class CrossProfileAppsTest { 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/graphics/drawable/IconTest.java b/core/tests/coretests/src/android/graphics/drawable/IconTest.java index 2bdcc284154b..75390a282af9 100644 --- a/core/tests/coretests/src/android/graphics/drawable/IconTest.java +++ b/core/tests/coretests/src/android/graphics/drawable/IconTest.java @@ -180,6 +180,61 @@ public class IconTest extends AndroidTestCase { } } + /** + * Icon resource test that ensures we can load and draw non-bitmaps. (In this case, + * stat_sys_adb is assumed, and asserted, to be a vector drawable.) + */ + @SmallTest + public void testWithStatSysAdbResource() throws Exception { + // establish reference bitmap + final float dp = getContext().getResources().getDisplayMetrics().density; + final int stat_sys_adb_width = (int) (24 * dp); + final int stat_sys_adb_height = (int) (24 * dp); + + final Drawable stat_sys_adb = getContext() + .getDrawable(com.android.internal.R.drawable.stat_sys_adb); + if (!(stat_sys_adb instanceof VectorDrawable)) { + fail("stat_sys_adb is a " + stat_sys_adb.toString() + + ", not a VectorDrawable; stat_sys_adb malformed"); + } + + if (stat_sys_adb.getIntrinsicWidth() != stat_sys_adb_width) { + fail("intrinsic width of stat_sys_adb is not 24dp; stat_sys_adb malformed"); + } + if (stat_sys_adb.getIntrinsicHeight() != stat_sys_adb_height) { + fail("intrinsic height of stat_sys_adb is not 24dp; stat_sys_adb malformed"); + } + final Bitmap referenceBitmap = Bitmap.createBitmap( + stat_sys_adb_width, + stat_sys_adb_height, + Bitmap.Config.ARGB_8888); + stat_sys_adb.setBounds(0, 0, stat_sys_adb_width, stat_sys_adb_height); + stat_sys_adb.draw(new Canvas(referenceBitmap)); + + final Icon im1 = Icon.createWithResource(getContext(), + com.android.internal.R.drawable.stat_sys_adb); + final Drawable draw1 = im1.loadDrawable(getContext()); + + assertEquals(stat_sys_adb.getIntrinsicWidth(), draw1.getIntrinsicWidth()); + assertEquals(stat_sys_adb.getIntrinsicHeight(), draw1.getIntrinsicHeight()); + assertEquals(im1.getResId(), com.android.internal.R.drawable.stat_sys_adb); + + final Bitmap test1 = Bitmap.createBitmap( + draw1.getIntrinsicWidth(), + draw1.getIntrinsicHeight(), + Bitmap.Config.ARGB_8888); + draw1.setBounds(0, 0, test1.getWidth(), test1.getHeight()); + draw1.draw(new Canvas(test1)); + + final File dir = getContext().getExternalFilesDir(null); + test1.compress(Bitmap.CompressFormat.PNG, 100, + new FileOutputStream(new File(dir, "testWithVectorDrawableResource-test.png"))); + if (!equalBitmaps(referenceBitmap, test1)) { + findBitmapDifferences(referenceBitmap, test1); + fail("testWithFile: file1 differs, check " + dir); + } + } + @SmallTest public void testWithFile() throws Exception { final Bitmap bit1 = ((BitmapDrawable) getContext().getDrawable(R.drawable.landscape)) diff --git a/core/tests/coretests/src/android/net/SntpClientTest.java b/core/tests/coretests/src/android/net/SntpClientTest.java index ba7df1e218d9..267fc2b636d6 100644 --- a/core/tests/coretests/src/android/net/SntpClientTest.java +++ b/core/tests/coretests/src/android/net/SntpClientTest.java @@ -295,7 +295,8 @@ public class SntpClientTest { @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 1ae9649dfe06..e303934c4aad 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 @@ import org.junit.runner.RunWith; @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 @@ public class HandwritingInitiatorTest { } @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 @@ public class HandwritingInitiatorTest { 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 8fa48ef5494d..94a149b09d54 100644 --- a/core/tests/coretests/src/android/window/BackNavigationTest.java +++ b/core/tests/coretests/src/android/window/BackNavigationTest.java @@ -111,12 +111,12 @@ public class BackNavigationTest { 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 f8c994416f46..212f4ed92b8c 100644 --- a/core/tests/coretests/src/android/window/WindowOnBackInvokedDispatcherTest.java +++ b/core/tests/coretests/src/android/window/WindowOnBackInvokedDispatcherTest.java @@ -77,9 +77,9 @@ public class WindowOnBackInvokedDispatcherTest { 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 @@ public class WindowOnBackInvokedDispatcherTest { 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 @@ public class WindowOnBackInvokedDispatcherTest { @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 @@ public class WindowOnBackInvokedDispatcherTest { 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 f5cbffb64bb5..7ccb9d963ee6 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 android.os.BatteryStats.WAKE_TYPE_PARTIAL; 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.os.WorkSource; 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 com.android.internal.power.MeasuredEnergyStats; import junit.framework.TestCase; +import org.mockito.Mock; + import java.util.Arrays; import java.util.HashMap; import java.util.Map; @@ -72,6 +80,13 @@ public class BatteryStatsNoteTest extends TestCase { 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 @@ public class BatteryStatsNoteTest extends TestCase { } @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 @@ public class BatteryStatsNoteTest extends TestCase { expectedDurationsMs[currentRat][currentFrequencyRange][currentSignalStrength] += inc; }; + state.setOnBattery(false); state.setModemActive(false); state.setRatType(TelephonyManager.NETWORK_TYPE_UNKNOWN, @@ -1260,95 +1236,367 @@ public class BatteryStatsNoteTest extends TestCase { 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 @@ public class BatteryStatsNoteTest extends TestCase { } 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); - - assertEquals(sb.toString(), expectedSignalStrengthDurationMs, actualDurationMs); + 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); + + 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 5adc9bdf0d00..483224cf353d 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_COMPONENT_ANY; 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 @@ public class BatteryUsageStatsTest { 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 @@ public class BatteryUsageStatsTest { 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 @@ public class BatteryUsageStatsTest { 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 @@ public class BatteryUsageStatsTest { 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 @@ public class BatteryUsageStatsTest { 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 @@ public class BatteryUsageStatsTest { 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 @@ public class BatteryUsageStatsTest { 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 @@ public class BatteryUsageStatsTest { .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 @@ public class BatteryUsageStatsTest { 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 @@ public class BatteryUsageStatsTest { 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 @@ public class BatteryUsageStatsTest { .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 @@ public class BatteryUsageStatsTest { 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 @@ public class BatteryUsageStatsTest { 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 @@ public class BatteryUsageStatsTest { 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 @@ public class BatteryUsageStatsTest { } 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 448f6664c2fa..fdbf071b7bba 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 @@ public class BluetoothPowerCalculatorTest { 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 @@ public class BluetoothPowerCalculatorTest { 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 b89e8bce5fc9..625f52a87ecf 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 @@ public final class LooperStatsTest { 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/app/activity/ActivityThreadClientTest.java b/core/tests/mockingcoretests/src/android/app/activity/ActivityThreadClientTest.java index f8db069b99ce..b006a1681a99 100644 --- a/core/tests/mockingcoretests/src/android/app/activity/ActivityThreadClientTest.java +++ b/core/tests/mockingcoretests/src/android/app/activity/ActivityThreadClientTest.java @@ -16,12 +16,15 @@ package android.app.activity; +import static android.app.ActivityThread.shouldReportChange; import static android.app.servertransaction.ActivityLifecycleItem.ON_CREATE; import static android.app.servertransaction.ActivityLifecycleItem.ON_DESTROY; import static android.app.servertransaction.ActivityLifecycleItem.ON_PAUSE; import static android.app.servertransaction.ActivityLifecycleItem.ON_RESUME; import static android.app.servertransaction.ActivityLifecycleItem.ON_START; import static android.app.servertransaction.ActivityLifecycleItem.ON_STOP; +import static android.content.pm.ActivityInfo.CONFIG_FONT_SCALE; +import static android.content.pm.ActivityInfo.CONFIG_SCREEN_SIZE; import static androidx.test.platform.app.InstrumentationRegistry.getInstrumentation; @@ -31,6 +34,8 @@ import static com.android.dx.mockito.inline.extended.ExtendedMockito.mockitoSess import static com.android.dx.mockito.inline.extended.ExtendedMockito.spyOn; import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.anyInt; import static org.mockito.Mockito.clearInvocations; @@ -56,6 +61,7 @@ import android.os.UserHandle; import android.platform.test.annotations.Presubmit; import android.testing.PollingCheck; import android.view.WindowManagerGlobal; +import android.window.SizeConfigurationBuckets; import androidx.test.annotation.UiThreadTest; import androidx.test.ext.junit.runners.AndroidJUnit4; @@ -195,6 +201,47 @@ public class ActivityThreadClientTest { } } + @Test + public void testShouldReportChange() { + final Configuration newConfig = new Configuration(); + final Configuration currentConfig = new Configuration(); + + assertFalse("Must not report change if no public diff", + shouldReportChange(0 /* publicDiff */, currentConfig, newConfig, + null /* sizeBuckets */, 0 /* handledConfigChanges */)); + + final int[] verticalThresholds = {100, 400}; + final SizeConfigurationBuckets buckets = new SizeConfigurationBuckets( + null /* horizontal */, + verticalThresholds, + null /* smallest */, + null /* screenLayoutSize */, + false /* screenLayoutLongSet */); + currentConfig.screenHeightDp = 200; + newConfig.screenHeightDp = 300; + + assertFalse("Must not report changes if the diff is small and not handled", + shouldReportChange(CONFIG_SCREEN_SIZE /* publicDiff */, currentConfig, + newConfig, buckets, CONFIG_FONT_SCALE /* handledConfigChanges */)); + + assertTrue("Must report changes if the small diff is handled", + shouldReportChange(CONFIG_SCREEN_SIZE /* publicDiff */, currentConfig, newConfig, + buckets, CONFIG_SCREEN_SIZE /* handledConfigChanges */)); + + currentConfig.fontScale = 0.8f; + newConfig.fontScale = 1.2f; + + assertTrue("Must report handled changes regardless of small unhandled change", + shouldReportChange(CONFIG_SCREEN_SIZE | CONFIG_FONT_SCALE /* publicDiff */, + currentConfig, newConfig, buckets, CONFIG_FONT_SCALE /* handledConfigChanges */)); + + newConfig.screenHeightDp = 500; + + assertFalse("Must not report changes if there's unhandled big changes", + shouldReportChange(CONFIG_SCREEN_SIZE | CONFIG_FONT_SCALE /* publicDiff */, + currentConfig, newConfig, buckets, CONFIG_FONT_SCALE /* handledConfigChanges */)); + } + private void recreateAndVerifyNoRelaunch(ActivityThread activityThread, TestActivity activity) { clearInvocations(activityThread); getInstrumentation().runOnMainSync(() -> activity.recreate()); diff --git a/core/tests/mockingcoretests/src/android/util/TimingsTraceLogTest.java b/core/tests/mockingcoretests/src/android/util/TimingsTraceLogTest.java index 5dc44d21c6b7..8de919681006 100644 --- a/core/tests/mockingcoretests/src/android/util/TimingsTraceLogTest.java +++ b/core/tests/mockingcoretests/src/android/util/TimingsTraceLogTest.java @@ -123,7 +123,7 @@ public class TimingsTraceLogTest { 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 @@ public class TimingsTraceLogTest { 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 @@ public class TimingsTraceLogTest { 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 @@ public class TimingsTraceLogTest { 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 2a82d8ecf5ee..df51871c57d9 100644 --- a/data/etc/Android.bp +++ b/data/etc/Android.bp @@ -71,14 +71,6 @@ prebuilt_etc { } 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 bc62bbc845f3..000000000000 --- 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 d1873a0f40cf..2d1db716b700 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 c3b0017bead6..a9730785723b 100644 --- a/data/etc/privapp-permissions-platform.xml +++ b/data/etc/privapp-permissions-platform.xml @@ -38,24 +38,6 @@ applications that come with the platform <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 @@ applications that come with the platform <!-- 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 @@ applications that come with the platform <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 df2b2a395ea7..4449c48d28bb 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 7e68bc06d506..1a522bd5e794 100644 --- a/graphics/java/android/graphics/Rect.java +++ b/graphics/java/android/graphics/Rect.java @@ -291,6 +291,14 @@ public final class Rect implements Parcelable { } /** + * @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 61f7facf0916..a2f5301e353f 100644 --- a/graphics/java/android/graphics/Typeface.java +++ b/graphics/java/android/graphics/Typeface.java @@ -329,7 +329,7 @@ public class Typeface { 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 cd7936d50dff..abd0be9c2872 100644 --- a/graphics/java/android/graphics/fonts/Font.java +++ b/graphics/java/android/graphics/fonts/Font.java @@ -179,7 +179,7 @@ public final class Font { */ 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 cffdf28dbc27..d083e444e996 100644 --- a/graphics/java/android/graphics/text/LineBreakConfig.java +++ b/graphics/java/android/graphics/text/LineBreakConfig.java @@ -26,7 +26,7 @@ import java.util.Objects; /** * 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,39 +78,96 @@ public final class LineBreakConfig { @Retention(RetentionPolicy.SOURCE) public @interface LineBreakWordStyle {} - private @LineBreakStyle int mLineBreakStyle = LINE_BREAK_STYLE_NONE; - private @LineBreakWordStyle int mLineBreakWordStyle = LINE_BREAK_WORD_STYLE_NONE; - - public LineBreakConfig() { + /** + * 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; + + // 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; + /** - * Get the line break style. - * - * @return The current line break style to be used for the text wrapping. + * Constructor with the line break parameters. + * Use the {@link LineBreakConfig.Builder} to create the LineBreakConfig instance. */ - public @LineBreakStyle int getLineBreakStyle() { - return mLineBreakStyle; + private LineBreakConfig(@LineBreakStyle int lineBreakStyle, + @LineBreakWordStyle int lineBreakWordStyle) { + mLineBreakStyle = lineBreakStyle; + mLineBreakWordStyle = lineBreakWordStyle; } /** - * Set the line break style. + * Get the line break style. * - * @param lineBreakStyle the new line break style. + * @return The current line break style to be used for the text wrapping. */ - public void setLineBreakStyle(@LineBreakStyle int lineBreakStyle) { - mLineBreakStyle = lineBreakStyle; + public @LineBreakStyle int getLineBreakStyle() { + return mLineBreakStyle; } /** @@ -122,15 +179,6 @@ public final class LineBreakConfig { 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 1d2b9384f47d..2aa695346c89 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 @@ public class SplitController implements JetpackTaskFragmentOrganizer.TaskFragmen 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 2c61df96eb03..780e4c1632f7 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/color/tv_pip_menu_close_icon.xml b/libs/WindowManager/Shell/res/color/tv_pip_menu_close_icon.xml new file mode 100644 index 000000000000..ce8640df0093 --- /dev/null +++ b/libs/WindowManager/Shell/res/color/tv_pip_menu_close_icon.xml @@ -0,0 +1,19 @@ +<?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:color="@color/tv_pip_menu_icon_unfocused" /> +</selector>
\ No newline at end of file diff --git a/libs/WindowManager/Shell/res/color/tv_pip_menu_close_icon_bg.xml b/libs/WindowManager/Shell/res/color/tv_pip_menu_close_icon_bg.xml new file mode 100644 index 000000000000..6cbf66f00df7 --- /dev/null +++ b/libs/WindowManager/Shell/res/color/tv_pip_menu_close_icon_bg.xml @@ -0,0 +1,21 @@ +<?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_focused="true" + android:color="@color/tv_pip_menu_close_icon_bg_focused" /> + <item android:color="@color/tv_pip_menu_close_icon_bg_unfocused" /> +</selector>
\ No newline at end of file diff --git a/libs/WindowManager/Shell/res/values-af/strings_tv.xml b/libs/WindowManager/Shell/res/values-af/strings_tv.xml index f552b81d9b77..c87bec093cca 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 6b6fe9fb8045..d23353858de6 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 a85d7b1c8da5..a1ceda5fc987 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 9e2f5502bbfe..8d7bd9f6a27e 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 670b02fa52c8..87c46fa41a01 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 de23d71f1a28..c87f30611a07 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 03de88c8b975..3566bc372820 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 38e1ef861be9..91049fd2cf02 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 0b24328d8c7c..792708d128a5 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 63e23c2edace..b7f0dca1b5a5 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 2ec1db4e990b..8a522b3e6397 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 e35390ad2abb..1c560c7afa06 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 9b38537eaa36..9a8cc2b4d70e 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 2f3b359f40e5..cba660ac723c 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 07fc28dc0583..02a1b66eb63f 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 1eba0b7caa0c..24cd030cd754 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 79a8b95263f2..82257b42814d 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 79a8b95263f2..82257b42814d 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 79a8b95263f2..82257b42814d 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 79a8b95263f2..82257b42814d 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 8925f183188c..a6e494cfed3c 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 1b1a41910242..458f6b15b857 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 29ff1c6105bb..0a690984dac5 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 f528bb2065b9..dc0232303a70 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 72f9980a97c3..bce06da2c66f 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 5fa59beae1a5..ff9a03c6cefb 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 217a85ceb791..3e8bf9032780 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 b6f401fae144..66e13b89c64b 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 ffa4a229b9f2..ed9baf5b6215 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 3a7ed890961c..a057434d7853 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 7a9bb25d63c2..d9525910e4c6 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 5776f8190868..d897ac73f80d 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 e4d69442c5c0..8f5f3164c4d7 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 43beeeaa44f5..fc8d79589121 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 e439d5c6fbbd..f5665b8dd166 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 25cb7567e33e..a1535653f679 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 56b973996ea9..70ca1afe3aea 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 735c5cd6c065..cda627517872 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 e4e0bf6002b0..30ce97b998ca 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 c8326a6552c4..e58e7bf6fabc 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 025e5a554de1..b09686646c8b 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 27afe2ec4131..7bade0dff0d9 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 86bad2776c37..721be1fc1650 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 3fbfdaa85a70..8310c8a1169c 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 fa8c898011fc..a3e055a515a1 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 6e2b810e9b8b..887ac52c8e43 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 3d4505d77d75..91c4a033356d 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 f907055872ca..04265ca01b48 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 04d9409cb3ac..8c6191e00833 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 e9ee13884afc..beef1fef862b 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 1ed6b6e566de..c2a532d09647 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 d4a6942ae9dc..bf8c59b57359 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 940f9832eb4a..5d519b7afe9a 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 f4b180c8fe74..08642c47c91a 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 4b2a5ecbce0c..e01daee115ca 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 be74eeb78bba..65ed0b7f5bff 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 a36cad696159..d33fed67efb6 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 eb7ec606b0fa..9763c5665ab2 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 e48199f9de50..e0344855bd1f 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 891107e765f6..9c01ac3f3cc0 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 7b5d08acd504..b922e2d5a6ba 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 b669f161c625..cc4eb3c32c1f 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 6c1fa5905d1a..c4ae78d89ba8 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 b669f161c625..cc4eb3c32c1f 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 8ecf8c5a1593..86a30f49df15 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 19f7a00c758b..08623e1e69c5 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 7444369cbc95..fbb0ebba0623 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 1a8edf183c75..81cb0eafc759 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 c4c04c24fc49..060aaa0ce647 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 2771b89a63eb..9bfdb6a3edd8 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 32440302d6d2..6bc5c87bab48 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 842c8053e494..b3465ab1db85 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 8728fd9360c2..baff49ed821a 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 e325b1a6c32d..4439e299c919 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 1381e6771936..35579346615f 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-television/config.xml b/libs/WindowManager/Shell/res/values-television/config.xml index dcb4c1026062..86ca65526336 100644 --- a/libs/WindowManager/Shell/res/values-television/config.xml +++ b/libs/WindowManager/Shell/res/values-television/config.xml @@ -39,4 +39,8 @@ <!-- Duration (in milliseconds) the PiP stays stashed before automatically unstashing. --> <integer name="config_pipStashDuration">5000</integer> + + <!-- Time (duration in milliseconds) that the shell waits for an app to close the PiP by itself + if a custom action is present before closing it. --> + <integer name="config_pipForceCloseDelay">5000</integer> </resources> diff --git a/libs/WindowManager/Shell/res/values-th/strings_tv.xml b/libs/WindowManager/Shell/res/values-th/strings_tv.xml index 6f0001890961..0a07d157ec6f 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 868b27874cc3..9a11a38fa492 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 9ffad78df41d..bf4bc6f1fff7 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 24c169807e58..7e9f54e68f54 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 c05729a123ed..c2ef69ff1488 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 43ab5ac11a80..9ab95c80aa25 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 368280c210bc..146376d3cab6 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 e5d879a24a6f..55407d2c699d 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 8ee5f11a76d8..15e278d8ecc2 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 b23ecdee3575..0b17b31d23d0 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 b14ee992b2ad..dad8c8128222 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/res/values/colors_tv.xml b/libs/WindowManager/Shell/res/values/colors_tv.xml index 08d3cef10428..64b146ec3a83 100644 --- a/libs/WindowManager/Shell/res/values/colors_tv.xml +++ b/libs/WindowManager/Shell/res/values/colors_tv.xml @@ -16,8 +16,10 @@ --> <resources> <color name="tv_pip_menu_icon_focused">#0E0E0F</color> - <color name="tv_pip_menu_icon_unfocused">#E8EAED</color> + <color name="tv_pip_menu_icon_unfocused">#F8F9FA</color> <color name="tv_pip_menu_icon_disabled">#80868B</color> + <color name="tv_pip_menu_close_icon_bg_focused">#D93025</color> + <color name="tv_pip_menu_close_icon_bg_unfocused">#D69F261F</color> <color name="tv_pip_menu_icon_bg_focused">#E8EAED</color> <color name="tv_pip_menu_icon_bg_unfocused">#990E0E0F</color> <color name="tv_pip_menu_focus_border">#E8EAED</color> 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 84429948c643..31f0ef0192ae 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 @@ public class ShellTaskOrganizer extends TaskOrganizer implements 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 8d5fdfbc8cb0..08cb252cdf43 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 @@ import com.android.wm.shell.common.annotations.ShellMainThread; */ 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 @@ public class BackAnimationController implements RemoteCallable<BackAnimationCont 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 @@ public class BackAnimationController implements RemoteCallable<BackAnimationCont 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 @@ public class BackAnimationController implements RemoteCallable<BackAnimationCont 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 @@ public class BackAnimationController implements RemoteCallable<BackAnimationCont } } + 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 @@ public class BackAnimationController implements RemoteCallable<BackAnimationCont 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 58f79f3600de..13d12b3589c0 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 @@ public class BubbleStackView extends FrameLayout 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 51067a45381c..8d1afa4a1304 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 @@ public class SystemWindows { @Override public void resized(ClientWindowFrames frames, boolean reportDraw, MergedConfiguration newMergedConfiguration, boolean forceLayout, - boolean alwaysConsumeSystemBars, int displayId) {} + boolean alwaysConsumeSystemBars, int displayId, int syncSeqId, int resizeMode) {} @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 b52c8d118711..daba7742661c 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 @@ public final class SplitLayout implements DisplayInsetsController.OnInsetsChange private WindowContainerToken mWinToken2; private int mDividePosition; private boolean mInitialized = false; + private boolean mFreezeDividerWindow = false; private int mOrientation; private int mRotation; @@ -225,11 +226,6 @@ public final class SplitLayout implements DisplayInsetsController.OnInsetsChange mDividerSnapAlgorithm = getSnapAlgorithm(mContext, mRootBounds, null); initDividerPosition(mTempRect); - if (mInitialized) { - release(); - init(); - } - return true; } @@ -298,20 +294,37 @@ public final class SplitLayout implements DisplayInsetsController.OnInsetsChange } /** 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 final class SplitLayout implements DisplayInsetsController.OnInsetsChange } } + 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 @@ public final class SplitLayout implements DisplayInsetsController.OnInsetsChange } 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 4903f9d46dc7..833d9d50701c 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 @@ public final class SplitWindowManager extends WindowlessWindowManager { 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 @@ public final class SplitWindowManager extends WindowlessWindowManager { * 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 b2bbafeb7bf5..99b32a677abe 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.SyncTransactionQueue; 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.Set; 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 @@ public class CompatUIController implements OnDisplaysChangedListener, 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 @@ public class CompatUIController implements OnDisplaysChangedListener, 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 @@ public class CompatUIController implements OnDisplaysChangedListener, 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 03986ee3b6d2..3061eab17d24 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 @@ package com.android.wm.shell.compatui.letterboxedu; 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 @@ import com.android.internal.policy.TransitionAnimation; 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 8aa4d0ee99ab..2e0b09e9d230 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 @@ class LetterboxEduDialogLayout extends ConstraintLayout { // 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 dda72ffb432f..cc3a3b2206f3 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.ShellTaskOrganizer; 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 @@ public class LetterboxEduWindowManager extends CompatUIWindowManagerAbstract { 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 class LetterboxEduWindowManager extends CompatUIWindowManagerAbstract { 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 @@ public class LetterboxEduWindowManager extends CompatUIWindowManagerAbstract { 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 @@ public class LetterboxEduWindowManager extends CompatUIWindowManagerAbstract { 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 bf0337dbd11a..026eeb09d741 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 com.android.wm.shell.unfold.ShellUnfoldProgressProvider; import java.util.Optional; import dagger.BindsOptionalOf; +import dagger.Lazy; import dagger.Module; import dagger.Provides; @@ -189,15 +190,13 @@ public abstract class WMShellBaseModule { @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 @@ public abstract class WMShellBaseModule { 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 429eb9963794..003c55977841 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.WindowContainerToken; 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.DisplayInsetsController; 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 @@ public class KidsModeTaskOrganizer extends ShellTaskOrganizer { 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 @@ public class KidsModeTaskOrganizer extends ShellTaskOrganizer { 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/PinnedStackListenerForwarder.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PinnedStackListenerForwarder.java index 3fefc4a0e0bf..87eca74acd0b 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PinnedStackListenerForwarder.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PinnedStackListenerForwarder.java @@ -72,9 +72,10 @@ public class PinnedStackListenerForwarder { } } - private void onActionsChanged(ParceledListSlice<RemoteAction> actions) { + private void onActionsChanged(ParceledListSlice<RemoteAction> actions, + RemoteAction closeAction) { for (PinnedTaskListener listener : mListeners) { - listener.onActionsChanged(actions); + listener.onActionsChanged(actions, closeAction); } } @@ -113,9 +114,10 @@ public class PinnedStackListenerForwarder { } @Override - public void onActionsChanged(ParceledListSlice<RemoteAction> actions) { + public void onActionsChanged(ParceledListSlice<RemoteAction> actions, + RemoteAction closeAction) { mMainExecutor.execute(() -> { - PinnedStackListenerForwarder.this.onActionsChanged(actions); + PinnedStackListenerForwarder.this.onActionsChanged(actions, closeAction); }); } @@ -152,7 +154,8 @@ public class PinnedStackListenerForwarder { public void onImeVisibilityChanged(boolean imeVisible, int imeHeight) {} - public void onActionsChanged(ParceledListSlice<RemoteAction> actions) {} + public void onActionsChanged(ParceledListSlice<RemoteAction> actions, + RemoteAction closeAction) {} public void onActivityHidden(ComponentName componentName) {} 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 c2d582354b13..7397e5273753 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 class PipBoundsAlgorithm { 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/PipMenuController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipMenuController.java index caa1f017082b..f6ff294b4328 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipMenuController.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipMenuController.java @@ -66,7 +66,7 @@ public interface PipMenuController { /** * Given a set of actions, update the menu. */ - void setAppActions(ParceledListSlice<RemoteAction> appActions); + void setAppActions(ParceledListSlice<RemoteAction> appActions, RemoteAction closeAction); /** * Resize the PiP menu with the given bounds. The PiP SurfaceControl is given if there is a 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 c1e78251da2b..5d6b041f9006 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 @@ public class PipTaskOrganizer implements ShellTaskOrganizer.TaskListener, */ 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 be713a59a816..e5a755c35add 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 @@ public class PipTransition extends PipTransitionController { 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 @@ public class PipTransition extends PipTransitionController { 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 @@ public class PipTransition extends PipTransitionController { 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 @@ public class PipTransition extends PipTransitionController { 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 @@ public class PipTransition extends PipTransitionController { 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/PhonePipMenuController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PhonePipMenuController.java index c4dadf1f739a..5e4c12ed37ed 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PhonePipMenuController.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PhonePipMenuController.java @@ -474,7 +474,8 @@ public class PhonePipMenuController implements PipMenuController { * Sets the menu actions to the actions provided by the current PiP menu. */ @Override - public void setAppActions(ParceledListSlice<RemoteAction> appActions) { + public void setAppActions(ParceledListSlice<RemoteAction> appActions, + RemoteAction closeAction) { mAppActions = appActions; updateMenuActions(); } diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipController.java index e7a1c4cca07e..e86ebaaabbfe 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipController.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipController.java @@ -246,8 +246,9 @@ public class PipController implements PipTransitionController.PipTransitionCallb } @Override - public void onActionsChanged(ParceledListSlice<RemoteAction> actions) { - mMenuController.setAppActions(actions); + public void onActionsChanged(ParceledListSlice<RemoteAction> actions, + RemoteAction closeAction) { + mMenuController.setAppActions(actions, closeAction); } @Override 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 3115f8afde3b..11633a91e8c6 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 @@ public class PipDismissTargetHandler implements ViewTreeObserver.OnPreDrawListen 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 d880f821ee73..986554853034 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 class TvPipBoundsState extends PipBoundsState { 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/pip/tv/TvPipController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/tv/TvPipController.java index f397ac01e60d..917eaa061d1b 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/tv/TvPipController.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/tv/TvPipController.java @@ -22,6 +22,7 @@ import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED; import android.annotation.IntDef; import android.app.ActivityManager; import android.app.ActivityTaskManager; +import android.app.PendingIntent; import android.app.RemoteAction; import android.app.TaskInfo; import android.content.ComponentName; @@ -69,7 +70,7 @@ public class TvPipController implements PipTransitionController.PipTransitionCal private static final int NONEXISTENT_TASK_ID = -1; @Retention(RetentionPolicy.SOURCE) - @IntDef(prefix = { "STATE_" }, value = { + @IntDef(prefix = {"STATE_"}, value = { STATE_NO_PIP, STATE_PIP, STATE_PIP_MENU, @@ -109,6 +110,10 @@ public class TvPipController implements PipTransitionController.PipTransitionCal private int mPinnedTaskId = NONEXISTENT_TASK_ID; private Runnable mUnstashRunnable; + private RemoteAction mCloseAction; + // How long the shell will wait for the app to close the PiP if a custom action is set. + private int mPipForceCloseDelay; + private int mResizeAnimationDuration; public static Pip create( @@ -369,9 +374,29 @@ public class TvPipController implements PipTransitionController.PipTransitionCal public void closePip() { if (DEBUG) { ProtoLog.d(ShellProtoLogGroup.WM_SHELL_PICTURE_IN_PICTURE, - "%s: closePip(), state=%s", TAG, stateToName(mState)); + "%s: closePip(), state=%s, loseAction=%s", TAG, stateToName(mState), + mCloseAction); } + if (mCloseAction != null) { + try { + mCloseAction.getActionIntent().send(); + } catch (PendingIntent.CanceledException e) { + ProtoLog.w(ShellProtoLogGroup.WM_SHELL_PICTURE_IN_PICTURE, + "%s: Failed to send close action, %s", TAG, e); + } + mMainExecutor.executeDelayed(() -> closeCurrentPiP(mPinnedTaskId), mPipForceCloseDelay); + } else { + closeCurrentPiP(mPinnedTaskId); + } + } + + private void closeCurrentPiP(int pinnedTaskId) { + if (mPinnedTaskId != pinnedTaskId) { + ProtoLog.d(ShellProtoLogGroup.WM_SHELL_PICTURE_IN_PICTURE, + "%s: PiP has already been closed by custom close action", TAG); + return; + } removeTask(mPinnedTaskId); onPipDisappeared(); } @@ -468,6 +493,7 @@ public class TvPipController implements PipTransitionController.PipTransitionCal private void loadConfigurations() { final Resources res = mContext.getResources(); mResizeAnimationDuration = res.getInteger(R.integer.config_pipResizeAnimationDuration); + mPipForceCloseDelay = res.getInteger(R.integer.config_pipForceCloseDelay); } private void registerTaskStackListenerCallback(TaskStackListenerImpl taskStackListener) { @@ -592,13 +618,15 @@ public class TvPipController implements PipTransitionController.PipTransitionCal public void onMovementBoundsChanged(boolean fromImeAdjustment) {} @Override - public void onActionsChanged(ParceledListSlice<RemoteAction> actions) { + public void onActionsChanged(ParceledListSlice<RemoteAction> actions, + RemoteAction closeAction) { if (DEBUG) { ProtoLog.d(ShellProtoLogGroup.WM_SHELL_PICTURE_IN_PICTURE, "%s: onActionsChanged()", TAG); } - mTvPipMenuController.setAppActions(actions); + mTvPipMenuController.setAppActions(actions, closeAction); + mCloseAction = closeAction; } }); } catch (RemoteException e) { @@ -617,7 +645,7 @@ public class TvPipController implements PipTransitionController.PipTransitionCal WINDOWING_MODE_PINNED, ACTIVITY_TYPE_UNDEFINED); if (DEBUG) { ProtoLog.d(ShellProtoLogGroup.WM_SHELL_PICTURE_IN_PICTURE, - "%s: > taskInfo=%s", TAG, taskInfo); + "%s: taskInfo=%s", TAG, taskInfo); } return taskInfo; } catch (RemoteException e) { diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/tv/TvPipMenuActionButton.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/tv/TvPipMenuActionButton.java index 4eb46d93c887..abbc614b4b4f 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/tv/TvPipMenuActionButton.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/tv/TvPipMenuActionButton.java @@ -126,4 +126,15 @@ public class TvPipMenuActionButton extends RelativeLayout implements View.OnClic public boolean isEnabled() { return mButtonView.isEnabled(); } + + void setIsCustomCloseAction(boolean isCustomCloseAction) { + mIconImageView.setImageTintList( + getResources().getColorStateList( + isCustomCloseAction ? R.color.tv_pip_menu_close_icon + : R.color.tv_pip_menu_icon)); + mButtonView.setBackgroundTintList(getResources() + .getColorStateList(isCustomCloseAction ? R.color.tv_pip_menu_close_icon_bg + : R.color.tv_pip_menu_icon_bg)); + } + } diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/tv/TvPipMenuController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/tv/TvPipMenuController.java index 1a035c5a68db..b6ae398c1eb9 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/tv/TvPipMenuController.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/tv/TvPipMenuController.java @@ -45,6 +45,7 @@ import com.android.wm.shell.protolog.ShellProtoLogGroup; import java.util.ArrayList; import java.util.List; +import java.util.Objects; /** * Manages the visibility of the PiP Menu as user interacts with PiP. @@ -67,6 +68,7 @@ public class TvPipMenuController implements PipMenuController, TvPipMenuView.Lis private final List<RemoteAction> mMediaActions = new ArrayList<>(); private final List<RemoteAction> mAppActions = new ArrayList<>(); + private RemoteAction mCloseAction; private SyncRtSurfaceTransactionApplier mApplier; RectF mTmpSourceRectF = new RectF(); @@ -270,12 +272,12 @@ public class TvPipMenuController implements PipMenuController, TvPipMenuView.Lis } @Override - public void setAppActions(ParceledListSlice<RemoteAction> actions) { + public void setAppActions(ParceledListSlice<RemoteAction> actions, RemoteAction closeAction) { if (DEBUG) { ProtoLog.d(ShellProtoLogGroup.WM_SHELL_PICTURE_IN_PICTURE, "%s: setAppActions()", TAG); } - updateAdditionalActionsList(mAppActions, actions.getList()); + updateAdditionalActionsList(mAppActions, actions.getList(), closeAction); } private void onMediaActionsChanged(List<RemoteAction> actions) { @@ -291,17 +293,19 @@ public class TvPipMenuController implements PipMenuController, TvPipMenuView.Lis enabledActions.add(remoteAction); } } - updateAdditionalActionsList(mMediaActions, enabledActions); + updateAdditionalActionsList(mMediaActions, enabledActions, mCloseAction); } - private void updateAdditionalActionsList( - List<RemoteAction> destination, @Nullable List<RemoteAction> source) { + private void updateAdditionalActionsList(List<RemoteAction> destination, + @Nullable List<RemoteAction> source, RemoteAction closeAction) { final int number = source != null ? source.size() : 0; - if (number == 0 && destination.isEmpty()) { + if (number == 0 && destination.isEmpty() && Objects.equals(closeAction, mCloseAction)) { // Nothing changed. return; } + mCloseAction = closeAction; + destination.clear(); if (number > 0) { destination.addAll(source); @@ -314,9 +318,9 @@ public class TvPipMenuController implements PipMenuController, TvPipMenuView.Lis return; } if (!mAppActions.isEmpty()) { - mPipMenuView.setAdditionalActions(mAppActions, mMainHandler); + mPipMenuView.setAdditionalActions(mAppActions, mCloseAction, mMainHandler); } else { - mPipMenuView.setAdditionalActions(mMediaActions, mMainHandler); + mPipMenuView.setAdditionalActions(mMediaActions, mCloseAction, mMainHandler); } } diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/tv/TvPipMenuView.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/tv/TvPipMenuView.java index 984dea2c016e..7fdb9ed90875 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/tv/TvPipMenuView.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/tv/TvPipMenuView.java @@ -50,6 +50,7 @@ import com.android.wm.shell.protolog.ShellProtoLogGroup; import java.util.ArrayList; import java.util.List; +import java.util.Objects; /** * A View that represents Pip Menu on TV. It's responsible for displaying 3 ever-present Pip Menu @@ -78,6 +79,7 @@ public class TvPipMenuView extends FrameLayout implements View.OnClickListener { private Rect mCurrentBounds; private final TvPipMenuActionButton mExpandButton; + private final TvPipMenuActionButton mCloseButton; public TvPipMenuView(@NonNull Context context) { this(context, null); @@ -100,8 +102,11 @@ public class TvPipMenuView extends FrameLayout implements View.OnClickListener { mActionButtonsContainer = findViewById(R.id.tv_pip_menu_action_buttons); mActionButtonsContainer.findViewById(R.id.tv_pip_menu_fullscreen_button) .setOnClickListener(this); - mActionButtonsContainer.findViewById(R.id.tv_pip_menu_close_button) - .setOnClickListener(this); + + mCloseButton = mActionButtonsContainer.findViewById(R.id.tv_pip_menu_close_button); + mCloseButton.setOnClickListener(this); + mCloseButton.setIsCustomCloseAction(true); + mActionButtonsContainer.findViewById(R.id.tv_pip_menu_move_button) .setOnClickListener(this); mExpandButton = findViewById(R.id.tv_pip_menu_expand_button); @@ -220,12 +225,24 @@ public class TvPipMenuView extends FrameLayout implements View.OnClickListener { || mArrowLeft.getAlpha() != 0f; } - void setAdditionalActions(List<RemoteAction> actions, Handler mainHandler) { + void setAdditionalActions(List<RemoteAction> actions, RemoteAction closeAction, + Handler mainHandler) { if (DEBUG) { ProtoLog.d(ShellProtoLogGroup.WM_SHELL_PICTURE_IN_PICTURE, "%s: setAdditionalActions()", TAG); } + // Replace system close action with custom close action if available + if (closeAction != null) { + setActionForButton(closeAction, mCloseButton, mainHandler); + } else { + mCloseButton.setTextAndDescription(R.string.pip_close); + mCloseButton.setImageResource(R.drawable.pip_ic_close_white); + } + mCloseButton.setIsCustomCloseAction(closeAction != null); + // Make sure the close action is always enabled + mCloseButton.setEnabled(true); + // Make sure we exactly as many additional buttons as we have actions to display. final int actionsNumber = actions.size(); int buttonsNumber = mAdditionalButtons.size(); @@ -256,14 +273,37 @@ public class TvPipMenuView extends FrameLayout implements View.OnClickListener { for (int index = 0; index < actionsNumber; index++) { final RemoteAction action = actions.get(index); final TvPipMenuActionButton button = mAdditionalButtons.get(index); - button.setVisibility(View.VISIBLE); // Ensure the button is visible. - button.setTextAndDescription(action.getContentDescription()); - button.setEnabled(action.isEnabled()); - button.setTag(action); - action.getIcon().loadDrawableAsync(mContext, button::setImageDrawable, mainHandler); + + // Remove action if it matches the custom close action. + if (actionsMatch(action, closeAction)) { + button.setVisibility(GONE); + continue; + } + setActionForButton(action, button, mainHandler); } } + /** + * Checks whether title, description and intent match. + * Comparing icons would be good, but using equals causes false negatives + */ + private boolean actionsMatch(RemoteAction action1, RemoteAction action2) { + if (action1 == action2) return true; + if (action1 == null) return false; + return Objects.equals(action1.getTitle(), action2.getTitle()) + && Objects.equals(action1.getContentDescription(), action2.getContentDescription()) + && Objects.equals(action1.getActionIntent(), action2.getActionIntent()); + } + + private void setActionForButton(RemoteAction action, TvPipMenuActionButton button, + Handler mainHandler) { + button.setVisibility(View.VISIBLE); // Ensure the button is visible. + button.setTextAndDescription(action.getContentDescription()); + button.setEnabled(action.isEnabled()); + button.setTag(action); + action.getIcon().loadDrawableAsync(mContext, button::setImageDrawable, mainHandler); + } + @Nullable SurfaceControl getWindowSurfaceControl() { final ViewRootImpl root = getViewRootImpl(); 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 e88eef976e5c..2da5becae8f5 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 @@ package com.android.wm.shell.splitscreen; 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.ActivityManager; 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.SingleInstanceRemoteListener; 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 @@ public class SplitScreenController implements DragAndDropPolicy.Starter, @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 class SplitScreenController implements DragAndDropPolicy.Starter, } } - 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 @@ public class SplitScreenController implements DragAndDropPolicy.Starter, 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 @@ public class SplitScreenController implements DragAndDropPolicy.Starter, } } - 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 @@ public class SplitScreenController implements DragAndDropPolicy.Starter, 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 @@ public class SplitScreenController implements DragAndDropPolicy.Starter, 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 48dd1fe3cb7e..ec1ddf077795 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_BACK; 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 @@ class StageCoordinator implements SplitLayout.SplitLayoutHandler, updateUnfoldBounds(); return; } + + mSplitLayout.update(null /* t */); onLayoutSizeChanged(mSplitLayout); } } @@ -1198,7 +1201,6 @@ class StageCoordinator implements SplitLayout.SplitLayoutHandler, 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 @@ class StageCoordinator implements SplitLayout.SplitLayoutHandler, @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 @@ class StageCoordinator implements SplitLayout.SplitLayoutHandler, // 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 @@ class StageCoordinator implements SplitLayout.SplitLayoutHandler, 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 1bef552e57ca..0d46199bde77 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.Point; 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 @@ public class TaskSnapshotWindow { 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 @@ public class TaskSnapshotWindow { 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 @@ public class TaskSnapshotWindow { @Override public void resized(ClientWindowFrames frames, boolean reportDraw, MergedConfiguration mergedConfiguration, boolean forceLayout, - boolean alwaysConsumeSystemBars, int displayId) { + boolean alwaysConsumeSystemBars, int displayId, int seqId, int resizeMode) { 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 a225f4ec8349..2aa63b3571ab 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 @@ public class DefaultTransitionHandler implements Transitions.TransitionHandler { } 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 fb3cd87448d1..435d67087f34 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 @@ public class Transitions implements RemoteCallable<Transitions> { /** 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 @@ public class Transitions implements RemoteCallable<Transitions> { 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 @@ public class Transitions implements RemoteCallable<Transitions> { 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 905468514a65..3e7ee25da5f8 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 @@ public class BackAnimationControllerTest { 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 9bb54a18063f..2e5078d86a8b 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 class SplitWindowManagerTests extends ShellTestCase { 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 a31b28737552..4607d8acc63e 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.DisplayLayout; 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.Captor; import org.mockito.Mock; import org.mockito.MockitoAnnotations; +import dagger.Lazy; + /** * Tests for {@link CompatUIController}. * @@ -82,6 +85,7 @@ public class CompatUIControllerTest extends ShellTestCase { 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 @@ public class CompatUIControllerTest extends ShellTestCase { 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 337b7385faec..7d51b521a9fb 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.ShellTaskOrganizer; 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 @@ public class LetterboxEduWindowManagerTest extends ShellTestCase { 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 @@ public class LetterboxEduWindowManagerTest extends ShellTestCase { } @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 @@ public class LetterboxEduWindowManagerTest extends ShellTestCase { } 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 @@ public class LetterboxEduWindowManagerTest extends ShellTestCase { 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 78903dca7657..ff6dfdb748c4 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.DisplayController; 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 @@ public class KidsModeTaskOrganizerTest { @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 @@ public class KidsModeTaskOrganizerTest { 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 dbf93b4d7e0a..a0b12976b467 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.any; 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 @@ import java.util.ArrayList; * Tests for the shell transitions. * * Build/Install/Run: - * atest WMShellUnitTests:ShellTransitionTests + * atest WMShellUnitTests:ShellTransitionTests */ @SmallTest @RunWith(AndroidJUnit4.class) @@ -600,6 +601,83 @@ public class ShellTransitionTests { 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 @@ public class ShellTransitionTests { 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 63b831de5da1..c80fb188e70f 100644 --- a/libs/androidfw/Android.bp +++ b/libs/androidfw/Android.bp @@ -118,7 +118,7 @@ cc_library { "libz", ], }, - linux_glibc: { + host_linux: { srcs: [ "CursorWindow.cpp", ], diff --git a/libs/hwui/HardwareBitmapUploader.cpp b/libs/hwui/HardwareBitmapUploader.cpp index dd272cd5ff7d..c24cabb287de 100644 --- a/libs/hwui/HardwareBitmapUploader.cpp +++ b/libs/hwui/HardwareBitmapUploader.cpp @@ -310,6 +310,11 @@ bool HardwareBitmapUploader::has1010102Support() { 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 @@ static FormatInfo determineFormat(const SkBitmap& skBitmap, bool usingGL) { } 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 34f43cd8a198..81057a24c29c 100644 --- a/libs/hwui/HardwareBitmapUploader.h +++ b/libs/hwui/HardwareBitmapUploader.h @@ -30,11 +30,13 @@ public: #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 bcfe9c3ecab4..30ca7d155c4c 100644 --- a/libs/hwui/Properties.cpp +++ b/libs/hwui/Properties.cpp @@ -135,7 +135,7 @@ bool Properties::load() { 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 1a89cfd5d0ad..67f47580a70f 100644 --- a/libs/hwui/hwui/Bitmap.cpp +++ b/libs/hwui/hwui/Bitmap.cpp @@ -104,6 +104,10 @@ sk_sp<Bitmap> Bitmap::allocateAshmemBitmap(size_t size, const SkImageInfo& info, 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 8c98c723dbb3..2357dfec72a6 100644 --- a/libs/hwui/renderthread/DrawFrameTask.cpp +++ b/libs/hwui/renderthread/DrawFrameTask.cpp @@ -133,6 +133,7 @@ int DrawFrameTask::drawFrame() { } 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 055dbb2b5c5e..99508a2943ff 100644 --- a/libs/storage/IMountService.cpp +++ b/libs/storage/IMountService.cpp @@ -48,8 +48,6 @@ enum { TRANSACTION_isObbMounted, TRANSACTION_getMountedObbPath, TRANSACTION_isExternalStorageEmulated, - TRANSACTION_decryptStorage, - TRANSACTION_encryptStorage, }; class BpMountService: public BpInterface<IMountService> @@ -517,40 +515,6 @@ public: 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 5b07318f4432..5a9c39bc021b 100644 --- a/libs/storage/include/storage/IMountService.h +++ b/libs/storage/include/storage/IMountService.h @@ -70,8 +70,6 @@ public: 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 000000000000..72b2374bad8f --- /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 1acdd1ecce0b..115cbec5e4de 100644 --- a/location/java/android/location/GnssReflectingPlane.java +++ b/location/java/android/location/GnssReflectingPlane.java @@ -22,9 +22,14 @@ import android.annotation.SystemApi; 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,24 +112,41 @@ public final class GnssReflectingPlane implements Parcelable { } }; + @Override + public void writeToParcel(@NonNull Parcel parcel, int flags) { + parcel.writeDouble(mLatitudeDegrees); + parcel.writeDouble(mLongitudeDegrees); + parcel.writeDouble(mAltitudeMeters); + parcel.writeDouble(mAzimuthDegrees); + } + @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)); + 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 void writeToParcel(@NonNull Parcel parcel, int flags) { - parcel.writeDouble(mLatitudeDegrees); - parcel.writeDouble(mLongitudeDegrees); - parcel.writeDouble(mAltitudeMeters); - parcel.writeDouble(mAzimuthDegrees); + 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} */ diff --git a/location/java/android/location/GnssSingleSatCorrection.java b/location/java/android/location/GnssSingleSatCorrection.java index 262630b79cb0..a7fce0aaaf6c 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 android.os.Parcelable; import com.android.internal.util.Preconditions; +import java.util.ArrayList; +import java.util.List; import java.util.Objects; /** @@ -36,106 +43,47 @@ import java.util.Objects; @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; - - /** - * 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; + 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; - /** 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 @@ public final class GnssSingleSatCorrection implements Parcelable { } /** - * 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 @@ public final class GnssSingleSatCorrection implements Parcelable { /** 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 @@ public final class GnssSingleSatCorrection implements Parcelable { 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 @@ public final class GnssSingleSatCorrection implements Parcelable { 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 @@ public final class GnssSingleSatCorrection implements Parcelable { @Override public boolean equals(Object obj) { - if (this == obj) { - return true; - } - 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; + 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); + } + return false; } @Override @@ -355,9 +302,10 @@ public final class GnssSingleSatCorrection implements Parcelable { mSatId, mCarrierFrequencyHz, mProbSatIsLos, - mExcessPathLengthMeters, - mExcessPathLengthUncertaintyMeters, - mReflectingPlane); + mCombinedExcessPathLengthMeters, + mCombinedExcessPathLengthUncertaintyMeters, + mCombinedAttenuationDb, + mGnssExcessPathInfoList); } @NonNull @@ -371,14 +319,19 @@ public final class GnssSingleSatCorrection implements Parcelable { 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 @@ public final class GnssSingleSatCorrection implements Parcelable { /** 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 @@ public final class GnssSingleSatCorrection implements Parcelable { 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 @@ public final class GnssSingleSatCorrection implements Parcelable { } /** - * 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 @@ public final class GnssSingleSatCorrection implements Parcelable { 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 fe0a14f37cb6..ec03a33d1c54 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 @@ public final class LastLocationRequest implements Parcelable { * * @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 @@ public final class LastLocationRequest implements Parcelable { * * @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 f1605f1ffe5d..033056cb2a69 100644 --- a/location/java/android/location/Location.java +++ b/location/java/android/location/Location.java @@ -132,31 +132,31 @@ public class Location implements Parcelable { } /** - * 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 @@ public class Location implements Parcelable { } /** - * 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 @@ public class Location implements Parcelable { } /** - * 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 @@ public class Location implements Parcelable { * 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 @@ public class Location implements Parcelable { * * @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 @@ public class Location implements Parcelable { * * @return elapsed realtime of this location in nanoseconds */ - public @IntRange long getElapsedRealtimeNanos() { + public @IntRange(from = 0) long getElapsedRealtimeNanos() { return mElapsedRealtimeNs; } @@ -302,7 +299,7 @@ public class Location implements Parcelable { * @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 @@ public class Location implements Parcelable { * * @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 @@ public class Location implements Parcelable { * @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 @@ public class Location implements Parcelable { * * @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 @@ public class Location implements Parcelable { * * @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 @@ public class Location implements Parcelable { * 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 @@ public class Location implements Parcelable { * * @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 @@ public class Location implements Parcelable { * * @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 @@ public class Location implements Parcelable { * * @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 @@ public class Location implements Parcelable { * * @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 @@ public class Location implements Parcelable { * 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 @@ public class Location implements Parcelable { * * @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 @@ public class Location implements Parcelable { * * @return vertical accuracy of this location */ - public @FloatRange float getVerticalAccuracyMeters() { + public @FloatRange(from = 0.0) float getVerticalAccuracyMeters() { return mAltitudeAccuracyMeters; } @@ -509,7 +507,7 @@ public class Location implements Parcelable { * * @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 @@ public class Location implements Parcelable { * * @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 @@ public class Location implements Parcelable { * * @return vertical accuracy of this location */ - public @FloatRange float getSpeedAccuracyMetersPerSecond() { + public @FloatRange(from = 0.0) float getSpeedAccuracyMetersPerSecond() { return mSpeedAccuracyMetersPerSecond; } @@ -585,7 +582,8 @@ public class Location implements Parcelable { * * @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 @@ public class Location implements Parcelable { * * @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 @@ public class Location implements Parcelable { * * @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 @@ public class Location implements Parcelable { * * @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 @@ public class Location implements Parcelable { } /** - * 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 @@ public class Location implements Parcelable { } /** - * 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 @@ public class Location implements Parcelable { * 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 @@ public class Location implements Parcelable { 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 @@ public class Location implements Parcelable { * @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 59c989b7f01e..a504cfe9789d 100644 --- a/location/java/android/location/LocationManager.java +++ b/location/java/android/location/LocationManager.java @@ -679,9 +679,8 @@ public class LocationManager { * * @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 59f4f5e8c19e..09474b503fc0 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 @@ public final class LocationRequest implements Parcelable { * @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 @@ public final class LocationRequest implements Parcelable { * * @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 @@ public final class LocationRequest implements Parcelable { * * @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 bdbb740a849b..c186700a4326 100755 --- a/media/java/android/media/IAudioService.aidl +++ b/media/java/android/media/IAudioService.aidl @@ -39,6 +39,7 @@ import android.media.IRecordingConfigDispatcher; 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 @@ interface IAudioService { 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/core/java/com/android/internal/logging/UiEvent.java b/media/java/android/media/ISpatializerHeadTrackerAvailableCallback.aidl index 0407b0704e80..dc5ee1d4e985 100644 --- a/core/java/com/android/internal/logging/UiEvent.java +++ b/media/java/android/media/ISpatializerHeadTrackerAvailableCallback.aidl @@ -1,5 +1,5 @@ /* - * Copyright (C) 2019 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,17 +14,14 @@ * limitations under the License. */ -package com.android.internal.logging; +package android.media; -import static java.lang.annotation.ElementType.FIELD; -import static java.lang.annotation.RetentionPolicy.SOURCE; - -import java.lang.annotation.Retention; -import java.lang.annotation.Target; +/** + * AIDL for the AudioService to signal whether audio device used by Spatializer has head tracker. + * + * {@hide} + */ +oneway interface ISpatializerHeadTrackerAvailableCallback { -@Retention(SOURCE) -@Target(FIELD) -public @interface UiEvent { - /** An explanation, suitable for Android analysts, of the UI event that this log represents. */ - String doc(); + void dispatchSpatializerHeadTrackerAvailable(boolean available); } diff --git a/media/java/android/media/MediaActionSound.java b/media/java/android/media/MediaActionSound.java index ec56d614f2b5..ad1405aa2356 100644 --- a/media/java/android/media/MediaActionSound.java +++ b/media/java/android/media/MediaActionSound.java @@ -25,7 +25,8 @@ import android.util.Log; /** * <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 @@ public class MediaActionSound { /** * <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 4563259c31f2..e39914db4d0f 100644 --- a/media/java/android/media/MediaCodec.java +++ b/media/java/android/media/MediaCodec.java @@ -223,19 +223,19 @@ import java.util.concurrent.locks.ReentrantLock; </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 @@ import java.util.concurrent.locks.ReentrantLock; <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 4956dbefa240..9dea5b9152b7 100644 --- a/media/java/android/media/MediaFormat.java +++ b/media/java/android/media/MediaFormat.java @@ -359,6 +359,42 @@ public final class MediaFormat { 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 @@ public final class MediaFormat { * 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 ee0293d629b1..283a41a81057 100644 --- a/media/java/android/media/MediaRoute2Info.java +++ b/media/java/android/media/MediaRoute2Info.java @@ -539,6 +539,7 @@ public final class MediaRoute2Info implements Parcelable { /** * Gets the Deduplication ID of the route if available. * @see RouteDiscoveryPreference#shouldRemoveDuplicates() + * @hide */ @NonNull public Set<String> getDeduplicationIds() { @@ -968,6 +969,7 @@ public final class MediaRoute2Info implements Parcelable { * <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 0ba36feb4ce9..207460af140c 100644 --- a/media/java/android/media/RouteDiscoveryPreference.java +++ b/media/java/android/media/RouteDiscoveryPreference.java @@ -119,6 +119,7 @@ public final class RouteDiscoveryPreference implements Parcelable { * first in the provided list will remain. * * @see #shouldRemoveDuplicates() + * @hide */ @NonNull public List<String> getDeduplicationPackageOrder() { @@ -130,6 +131,7 @@ public final class RouteDiscoveryPreference implements Parcelable { * <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 @@ public final class RouteDiscoveryPreference implements Parcelable { * Gets whether duplicate routes removal is enabled. * * @see #getDeduplicationPackageOrder() + * @hide */ public boolean shouldRemoveDuplicates() { return !mPackageOrder.isEmpty(); @@ -293,6 +296,7 @@ public final class RouteDiscoveryPreference implements Parcelable { * <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 @@ public final class RouteDiscoveryPreference implements Parcelable { * * @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 be0ef37345ed..74ca4b858ff6 100644 --- a/media/java/android/media/Spatializer.java +++ b/media/java/android/media/Spatializer.java @@ -185,6 +185,45 @@ public class Spatializer { 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 @@ public class Spatializer { @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 @@ public class Spatializer { /** * @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 @@ public class Spatializer { 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 @@ public class Spatializer { } //----------------------------------------------------------------------------- + // 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 19fc0521d7aa..b136d5bc4db3 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 @@ interface IMediaProjection { 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 4dde5e8d39a2..b5f95938f845 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.DisplayManager; 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 @@ public final class MediaProjection { @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 @@ public final class MediaProjection { } /** - * 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 0542c5598c01..f2fb93d803a8 100644 --- a/media/java/android/media/tv/AdRequest.java +++ b/media/java/android/media/tv/AdRequest.java @@ -163,7 +163,11 @@ public final class AdRequest implements Parcelable { /** * 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 8e80a62be3de..c88a2b5048df 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 @@ public final class AitInfo implements Parcelable { /** * 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 @@ public final class AitInfo implements Parcelable { /** * 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 ffb6e07bc485..3245fb504f85 100644 --- a/media/java/android/media/tv/CommandRequest.java +++ b/media/java/android/media/tv/CommandRequest.java @@ -24,6 +24,8 @@ import android.os.Parcelable; * 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 @@ public final class CommandRequest extends BroadcastInfoRequest implements Parcel } }; - 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 @@ public final class CommandRequest extends BroadcastInfoRequest implements Parcel 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 @@ public final class CommandRequest extends BroadcastInfoRequest implements Parcel @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 c8853f1d8373..8e448cdbd707 100644 --- a/media/java/android/media/tv/CommandResponse.java +++ b/media/java/android/media/tv/CommandResponse.java @@ -25,6 +25,8 @@ import android.os.Parcelable; * 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 @@ public final class CommandResponse extends BroadcastInfoResponse implements Parc }; 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 @@ public final class CommandResponse extends BroadcastInfoResponse implements Parc 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 final class CommandResponse extends BroadcastInfoResponse implements Parc 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 5957528554dc..078e83222e4e 100644 --- a/media/java/android/media/tv/SectionRequest.java +++ b/media/java/android/media/tv/SectionRequest.java @@ -80,6 +80,11 @@ public final class SectionRequest extends BroadcastInfoRequest implements Parcel /** * 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 35836bed385f..f38ea9dfac99 100644 --- a/media/java/android/media/tv/SectionResponse.java +++ b/media/java/android/media/tv/SectionResponse.java @@ -74,14 +74,20 @@ public final class SectionResponse extends BroadcastInfoResponse implements Parc } /** - * 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 f952ce929842..28dff374d539 100644 --- a/media/java/android/media/tv/StreamEventResponse.java +++ b/media/java/android/media/tv/StreamEventResponse.java @@ -43,7 +43,7 @@ public final class StreamEventResponse extends BroadcastInfoResponse implements }; 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 final class StreamEventResponse extends BroadcastInfoResponse implements } 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 @@ public final class StreamEventResponse extends BroadcastInfoResponse implements /** * 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 final class StreamEventResponse extends BroadcastInfoResponse implements 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 37df4eaf1ed0..a1a6b516859c 100644 --- a/media/java/android/media/tv/TableRequest.java +++ b/media/java/android/media/tv/TableRequest.java @@ -91,7 +91,12 @@ public final class TableRequest extends BroadcastInfoRequest implements Parcelab } /** - * 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 e9f1136875f5..afc9bee5fb85 100644 --- a/media/java/android/media/tv/TableResponse.java +++ b/media/java/android/media/tv/TableResponse.java @@ -76,7 +76,12 @@ public final class TableResponse extends BroadcastInfoResponse implements Parcel } /** - * 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 fbeb0c4bf268..7de30f579a35 100644 --- a/media/java/android/media/tv/TimelineResponse.java +++ b/media/java/android/media/tv/TimelineResponse.java @@ -18,6 +18,7 @@ package android.media.tv; import android.annotation.NonNull; import android.annotation.Nullable; +import android.net.Uri; import android.os.Parcel; import android.os.Parcelable; @@ -79,8 +80,8 @@ public final class TimelineResponse extends BroadcastInfoResponse implements Par * 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 69fe5ee49872..149c2f471a4c 100644 --- a/media/java/android/media/tv/TvInputManager.java +++ b/media/java/android/media/tv/TvInputManager.java @@ -680,7 +680,7 @@ public final class TvInputManager { * @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 @@ public final class TvInputManager { 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 4d63af7be474..ff3d06c5bd69 100644 --- a/media/java/android/media/tv/TvView.java +++ b/media/java/android/media/tv/TvView.java @@ -1083,7 +1083,7 @@ public class TvView extends ViewGroup { * @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 @@ public class TvView extends ViewGroup { } @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 6759fc499e1c..f551c9fcf6c7 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 0eb6fa8996d6..d5e995cbcfab 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 @@ import android.os.Parcelable; */ 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 @@ public final class AppLinkInfo implements Parcelable { 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 @@ public final class AppLinkInfo implements Parcelable { } /* 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 @@ public final class AppLinkInfo implements Parcelable { 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 a3e58d16f655..50aa6febacf7 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 @@ oneway interface ITvInteractiveAppClient { 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 aaabe342d9f1..9ff564ea3737 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.TvTrackInfo; 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 @@ import android.view.Surface; * @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 @@ interface ITvInteractiveAppManager { 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 23be4c64fcc4..fed86dc9e0a8 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 @@ interface ITvInteractiveAppManagerCallback { 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 b6d518ff7242..fb58ca7843ef 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 @@ oneway interface ITvInteractiveAppService { 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 970b94327572..87b3c1df6197 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 c449d2475428..e14b2bb18ea6 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 @@ oneway interface ITvInteractiveAppSession { 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 385f0d4f766a..32b08b7042fe 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 @@ oneway interface ITvInteractiveAppSessionCallback { 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 9eb4a6c393ab..d3cbcdc9a255 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.AdResponse; 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 @@ public final class TvInteractiveAppManager { * * @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 @@ public final class TvInteractiveAppManager { * * @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 final class TvInteractiveAppManager { */ 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 @@ public final class TvInteractiveAppManager { } @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 @@ public final class TvInteractiveAppManager { } @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 @@ public final class TvInteractiveAppManager { * 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 final class TvInteractiveAppManager { */ 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 final class TvInteractiveAppManager { }); } - 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 @@ public final class TvInteractiveAppManager { /** * 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 @@ public final class TvInteractiveAppManager { } /** - * 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 @@ public final class TvInteractiveAppManager { * 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 @@ public final class TvInteractiveAppManager { * 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 @@ public final class TvInteractiveAppManager { } } + 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 @@ public final class TvInteractiveAppManager { }); } + 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 @@ public final class TvInteractiveAppManager { * 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 d22fd83872e1..b103b1036303 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.CallSuper; 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 @@ public abstract class TvInteractiveAppService extends Service { } @Override - public void prepare(int type) { - onPrepare(type); - } - - @Override public void registerAppLinkInfo(AppLinkInfo appLinkInfo) { onRegisterAppLinkInfo(appLinkInfo); } @@ -240,11 +236,6 @@ public abstract class TvInteractiveAppService extends Service { } /** - * 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 @@ public abstract class TvInteractiveAppService extends Service { @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 @@ public abstract class TvInteractiveAppService extends Service { * {@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 @@ public abstract class TvInteractiveAppService extends Service { } /** + * 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 @@ public abstract class TvInteractiveAppService extends Service { * 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 @@ public abstract class TvInteractiveAppService extends Service { * 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 @@ public abstract class TvInteractiveAppService extends Service { /** * 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 @@ public abstract class TvInteractiveAppService extends Service { } /** + * 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 @@ public abstract class TvInteractiveAppService extends Service { * 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 @@ public abstract class TvInteractiveAppService extends Service { } /** + * 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 @@ public abstract class TvInteractiveAppService extends Service { } 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 @@ public abstract class TvInteractiveAppService extends Service { onCurrentTvInputId(inputId); } + void sendSigningResult(String signingId, byte[] result) { + onSigningResult(signingId, result); + } + void release() { onRelease(); if (mSurface != null) { @@ -1074,7 +1133,7 @@ public abstract class TvInteractiveAppService extends Service { * @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 @@ public abstract class TvInteractiveAppService extends Service { } @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 index 5e1501677b3b..4b6127c01d1e 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 index 6103db001b19..3e0885214dcd 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 @@ import java.util.List; /** * 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 @@ public final class TvInteractiveAppInfo implements Parcelable { 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 @@ public final class TvInteractiveAppInfo implements Parcelable { 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 773e54f30744..1df757b2d9d7 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.View; 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 @@ public class TvInteractiveAppView extends ViewGroup { 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 @@ public class TvInteractiveAppView extends ViewGroup { /** * 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 @@ public class TvInteractiveAppView extends ViewGroup { /** * Clears the callback. + * + * @see #setCallback(Executor, TvInteractiveAppCallback) */ public void clearCallback() { synchronized (mCallbackLock) { @@ -238,7 +278,9 @@ public class TvInteractiveAppView extends ViewGroup { } /** - * 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 @@ public class TvInteractiveAppView extends ViewGroup { 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 @@ public class TvInteractiveAppView extends ViewGroup { } /** - * 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 @@ public class TvInteractiveAppView extends ViewGroup { /** * Resets the interactive application. + * + * <p>This releases the resources of the corresponding {@link TvInteractiveAppService.Session}. */ public void resetInteractiveApp() { if (DEBUG) { @@ -471,6 +529,8 @@ public class TvInteractiveAppView extends ViewGroup { /** * 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 @@ public class TvInteractiveAppView extends ViewGroup { } } + /** + * 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 @@ public class TvInteractiveAppView extends ViewGroup { * <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 class TvInteractiveAppView extends ViewGroup { 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 @@ public class TvInteractiveAppView extends ViewGroup { 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 3fb3fd475ab3..5c90fd019cd8 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 d6b6bf8d1e56..3c790f0e24ee 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.Handler; 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 @@ public class BackupRestoreConfirmation extends Activity { Handler mHandler; IBackupManager mBackupManager; - IStorageManager mStorageManager; FullObserver mObserver; int mToken; - boolean mIsEncrypted; boolean mDidAcknowledge; String mAction; @@ -144,7 +140,6 @@ public class BackupRestoreConfirmation extends Activity { } 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 @@ public class BackupRestoreConfirmation extends Activity { 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 @@ public class BackupRestoreConfirmation extends Activity { } } - 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 56e5dca0f72f..aebc5d5adf6e 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 ece7bbafc654..ebe16a7a14e5 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 7df92bb145cb..3cd7929bdd83 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 55e96f6d7512..2cff4737cabf 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 f9ec5d0dce55..8e92051faf6c 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 93a0cba769c6..d1ec8637775c 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 f8515c33d57f..2a8eb24bcf1f 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 4ac4d04b184e..e5825bcbf70c 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 d8b7f59185c8..406a3b5dada5 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 44a40b9fede3..d7a28d949997 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 8eec33aeb4ee..c37054e9e98d 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_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" /> - <Button - android:id="@+id/btn_positive" - style="@style/PositiveButton" - android:text="@string/consent_yes" /> + </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" - android:layout_marginLeft="170dp" - android:layout_marginBottom="10dp" style="@style/NegativeButtonMultipleDevices" - android:textColor = "?android:textColorPrimary" + 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 7c508147e0ac..3d0849356281 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 c177039891d2..a22ca941c5eb 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 3c8a81f4fe83..eeb988f364b2 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 79aa4e7e8927..3dce38d0dc20 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 d04eadfb62f4..5f6aa9419c6e 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 2d8ef7348dfd..eec09d20eec1 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 5cb306f14380..0411f3aa3f4d 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 b4c74ad07e40..5c00999d6a31 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 b2865dc79ad5..dbb5c3b000a8 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 e8e4e7631481..a0b5b8c0c3fd 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 5d98a13e660e..78cac0a8c092 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 3a57bcc34fb6..ed521b1bf6fa 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 d29a9081afc0..fe65bda4b434 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 7d0b097f2a99..58c6c265aa96 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 a723da8f59a4..1ce89443afff 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 de7e2256ede8..0b1847692faf 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 f195e54f743c..f89f17ef0c66 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 a2aa5dddb43c..e366bb91d6ac 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 2b5ab117900e..440e06b54304 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 339f85a58127..326527c5b0a5 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 d59641111959..9b8f95942983 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 d59641111959..9b8f95942983 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 d59641111959..9b8f95942983 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 d59641111959..9b8f95942983 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 9f17a89099d6..8bd1c4a76735 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 5423d3eeff87..e5b22a2ed01b 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 ccbdd250dad2..1a988e96aaef 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 d8f1e9920736..f3b8ea92817c 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 de768249916c..0d4f073be50b 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 65ed2dde864f..cb14c27c333e 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 c8dbeb54402a..a1c15f131892 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 3d5898b0a5a9..5bc04397f5fa 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 ecd89aa97ec9..acf4cd6d2ef2 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 d060f29a7e02..d5f851580839 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 d06d8c677fd4..adfc6a0cc938 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 1be6af8af0ec..71c5f12d4ac2 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 610b7bdffa70..fd7e30275ddf 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 625a3e9cd4aa..c9ef48ad83f7 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 f09441fcdb4c..77c8befc6e24 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 ef52808cd5ff..ff4363cc7c59 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 c0ca2fcf3ba3..b8646c7ae976 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 5f88b7a68432..4dfb69bbc7d1 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 4a811f0aef9d..a6373c108b55 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 5e8d544d9b6a..392ca0aa74d4 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 3b179bf237dd..f057b8bcc448 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 a7efb15ed0be..365020c58853 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 b18586316289..e1dbaf5fbc5b 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 64576ce8aec8..0d01ce7cdce7 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 5bf8eb4ae6ac..2b98ce3875c6 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 714dc9365bd6..1f320dda3591 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 95cab696240f..debbf760fb17 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 5d32fbbf9116..3904ad317acb 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 cabfc77bb27c..71bc79201f92 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 b4531b5c864e..851651f59a5f 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 85952ca65fce..9e330e64c0e4 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 c0d589d0aca7..00c032d4aa18 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 0ce6ab712eb0..303b141a72e4 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 2ca812889342..e234089857d5 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 1fb20bf2449e..61a60b20fc33 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 aa73f5dff065..078a2d4a64cf 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 3ba75eb31aad..fd8a6cf23ba7 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 bc09a58afee1..76ec957ebf73 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 92d0a5ef5f1d..6b6649290802 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 c28be2543707..93b018e3e54e 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 f9fd206250d9..a15af4b51dfb 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 161188c70c6c..7d2282371d39 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 9124a405198a..e0c717c1f9ff 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 161188c70c6c..7d2282371d39 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 da7ae9e0f1bd..61b47fbb7d71 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 dbb09c9e7c96..062314f337b6 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 a3de2a393181..65f7865d4671 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 dd75ef590913..167eac8c8fdc 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 7cb5fb58fb60..5b795826c42d 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 62c711abf398..b69fa8afd092 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 8d51c62fd3e7..d40a11295833 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 ca1ec8769675..fff01ed727c9 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 cf9260087bd2..2533a97550ea 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 b86ea1cffacf..3f55444fa5c9 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 73cf3e88e180..552834e4ea25 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 6f29346debc5..c15ce034aceb 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 e557a385dd98..ee5ec161c195 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 c75214bf957e..07a5c2a29fbd 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 46a25b2ba185..8ab5bf1c6322 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 c9f930f0f54b..0c3686567826 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 91fdd946edf2..59fc98f5a907 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 4f96bd4d7f1a..8a96c4a7d1f2 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 3fdccf229bf8..1ee43c91d53b 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 a4dc0c9b6c81..fa2f0fc0961d 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 eec042429ca8..abefde4c0288 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 be5a195fa5f7..1c7cad33c0a7 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 55a199813388..67fc6c2dc864 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 6eaffd4c3cfe..a55f30c9be6a 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: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:background">@drawable/dialog_background</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 f752b697c4a5..0bdf65d8ef55 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.Button; 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 @@ public class CompanionDeviceActivity extends FragmentActivity implements 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 @@ public class CompanionDeviceActivity extends FragmentActivity implements 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 @@ public class CompanionDeviceActivity extends FragmentActivity implements 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 @@ public class CompanionDeviceActivity extends FragmentActivity implements 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 5f07fcfd8565..e8a1a5cc1916 100644 --- a/packages/CompanionDeviceManager/src/com/android/companiondevicemanager/CompanionDeviceDiscoveryService.java +++ b/packages/CompanionDeviceManager/src/com/android/companiondevicemanager/CompanionDeviceDiscoveryService.java @@ -150,6 +150,8 @@ public class CompanionDeviceDiscoveryService extends Service { mBtAdapter = mBtManager.getAdapter(); mBleScanner = mBtAdapter.getBluetoothLeScanner(); mWifiManager = getSystemService(WifiManager.class); + + sScanResultsLiveData.setValue(Collections.emptyList()); } @Override @@ -186,7 +188,6 @@ public class CompanionDeviceDiscoveryService extends Service { 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 8babd3ade1eb..328c67ebb216 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.view.ViewGroup; 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 @@ class DeviceListAdapter extends RecyclerView.Adapter<DeviceListAdapter.ViewHolde 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 217a1f67c336..bc278528570f 100644 --- a/packages/ConnectivityT/framework-t/Android.bp +++ b/packages/ConnectivityT/framework-t/Android.bp @@ -131,8 +131,8 @@ filegroup { "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 2b6570a6ecb0..74fe4bd46cde 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 @@ public final class NetworkStats implements AutoCloseable { /** * 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 @@ public final class NetworkStats implements AutoCloseable { * @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 @@ public final class NetworkStats implements AutoCloseable { * @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 ca080ce4c64a..f41475bea190 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 @@ public class NetworkStatsManager { * 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 @@ public class NetworkStatsManager { * 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 @@ public class NetworkStatsManager { * 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 @@ public class NetworkStatsManager { * * @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 @@ public class NetworkStatsManager { /** * 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 @@ public class NetworkStatsManager { * 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 @@ public class NetworkStatsManager { * 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 @@ public class NetworkStatsManager { * * @hide */ - @SystemApi + @SystemApi(client = MODULE_LIBRARIES) @RequiresPermission(anyOf = { NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK, android.Manifest.permission.NETWORK_STACK}) @@ -724,7 +763,7 @@ public class NetworkStatsManager { * * @hide */ - @SystemApi + @SystemApi(client = MODULE_LIBRARIES) @RequiresPermission(anyOf = { NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK, android.Manifest.permission.NETWORK_STACK}) @@ -785,10 +824,28 @@ public class NetworkStatsManager { /** * 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 @@ public class NetworkStatsManager { * @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 @@ public class NetworkStatsManager { * * @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 @@ public class NetworkStatsManager { /** * 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 @@ public class NetworkStatsManager { @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 @@ public class NetworkStatsManager { @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 @@ public class NetworkStatsManager { } } - 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 @@ public class NetworkStatsManager { @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 793f28d5aa59..e02ea897dbe6 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.compat.annotation.UnsupportedAppUsage; 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 com.android.modules.utils.BackgroundThread; 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 @@ public class EthernetManager { 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 @@ public class EthernetManager { } }; - 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,16 +323,22 @@ public class EthernetManager { 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(); } + } /** @@ -323,15 +363,20 @@ public class EthernetManager { @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 @@ public class EthernetManager { 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 onResult(@NonNull String iface) { + mExecutor.execute(() -> mCallback.onResult(iface)); } @Override - public void onComplete( - @Nullable final Network network, - @Nullable final EthernetNetworkManagementException e) { - mExecutor.execute(() -> mListener.accept(network, e)); + 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 @@ public class EthernetManager { * 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 @@ public class EthernetManager { @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 @@ public class EthernetManager { } /** - * 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 @@ public class EthernetManager { 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 @@ public class EthernetManager { } /** - * 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 @@ public class EthernetManager { 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 43f4c40f2d27..1691942c3675 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 @@ import java.util.Objects; */ @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 @@ public final class EthernetNetworkUpdateRequest implements Parcelable { 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 final class EthernetNetworkUpdateRequest implements Parcelable { */ 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 @@ public final class EthernetNetworkUpdateRequest implements Parcelable { * @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 @@ public final class EthernetNetworkUpdateRequest implements Parcelable { /** * 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 544d02ba76ff..42e4c1ac55aa 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 @@ package android.net; 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 @@ interface IEthernetManager 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 6d2ba03f78d4..751605bb3849 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 @@ import android.net.IpConfiguration; /** @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 index 93edccfdafd9..85795ead7aea 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 efe626d3c939..c86f7fd0890d 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 @@ interface INetworkStatsService { 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 f681ba1c3853..bcfeab96081a 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 final class NetworkStats implements Parcelable, Iterable<NetworkStats.Ent 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 @@ public final class NetworkStats implements Parcelable, Iterable<NetworkStats.Ent * @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 @@ public final class NetworkStats implements Parcelable, Iterable<NetworkStats.Ent /** * @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 @@ public final class NetworkStats implements Parcelable, Iterable<NetworkStats.Ent * 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 bc836d857e3e..dc4ac552a4bb 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 @@ public class TrafficStats { * 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 @@ public class TrafficStats { * * @hide */ - @SystemApi + @SystemApi(client = MODULE_LIBRARIES) public static void setThreadStatsTagDownload() { setThreadStatsTag(TAG_SYSTEM_DOWNLOAD); } @@ -468,7 +468,7 @@ public class TrafficStats { * * @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 @@ public class TrafficStats { * 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 @@ public class TrafficStats { * * @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 @@ public class TrafficStats { * * @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 @@ public class TrafficStats { * 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 7eaa01e262fe..01ff02dfc5b3 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 @@ import android.net.NetworkStats; 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 23fc06927ef9..d37a53dbf1e9 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 @@ public abstract class NetworkStatsProvider { 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 1d22908e1393..e3794e441a23 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 @@ public class NetworkStatsService extends INetworkStatsService.Stub { } @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 @@ public class NetworkStatsService extends INetworkStatsService.Stub { } @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 ad86f4667f67..b8f54b3faf63 100644 --- a/packages/DynamicSystemInstallationService/Android.bp +++ b/packages/DynamicSystemInstallationService/Android.bp @@ -22,6 +22,9 @@ android_app { defaults: ["platform_app_defaults"], srcs: ["src/**/*.java"], + static_libs: [ + "DynamicSystemInstallationService-logtags", + ], resource_dirs: ["res"], certificate: "platform", @@ -32,3 +35,8 @@ android_app { 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 f8cb5d3d2419..02128d480678 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.RemoteException; 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 @@ public class DynamicSystemInstallationService extends Service 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 @@ public class DynamicSystemInstallationService extends Service 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 @@ public class DynamicSystemInstallationService extends Service @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 @@ public class DynamicSystemInstallationService extends Service 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 @@ public class DynamicSystemInstallationService extends Service 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 @@ public class DynamicSystemInstallationService extends Service case STATUS_IN_PROGRESS: builder.setContentText(getString(R.string.notification_install_inprogress)); - int max = 1024; - int progress = 0; - - int currentMax = max >> (mNumInstalledPartitions + 1); - progress = max - currentMax * 2; + if (mInstallTaskProgress != null) { + int max = 1024; + int progress = 0; - long currentProgress = (mCurrentPartitionInstalledSize >> 20) * currentMax - / Math.max(mCurrentPartitionSize >> 20, 1); + int currentMax = max >> mInstallTaskProgress.partitionNumber; + progress = max - currentMax * 2; - progress += (int) currentProgress; + long currentProgress = + (mInstallTaskProgress.installedSize >> 20) + * currentMax + / Math.max(mInstallTaskProgress.partitionSize >> 20, 1); - builder.setProgress(max, progress, false); + progress += (int) currentProgress; + 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 @@ public class DynamicSystemInstallationService extends Service 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 @@ public class DynamicSystemInstallationService extends Service 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 000000000000..eae9de937700 --- /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 f18d4269c3ef..b439f8421b73 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.ZipEntry; 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 @@ class InstallationAsyncTask extends AsyncTask<String, InstallationAsyncTask.Prog static class Progress { public final String partitionName; + public final long installedSize; public final long partitionSize; - public final int numInstalledPartitions; - public long installedSize; - - Progress(String partitionName, long partitionSize, int numInstalledPartitions) { + public final int partitionNumber; + public final int totalPartitionNumber; + + 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 @@ class InstallationAsyncTask extends AsyncTask<String, InstallationAsyncTask.Prog 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 @@ class InstallationAsyncTask extends AsyncTask<String, InstallationAsyncTask.Prog 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 @@ class InstallationAsyncTask extends AsyncTask<String, InstallationAsyncTask.Prog 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 @@ class InstallationAsyncTask extends AsyncTask<String, InstallationAsyncTask.Prog } @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 @@ class InstallationAsyncTask extends AsyncTask<String, InstallationAsyncTask.Prog 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 @@ class InstallationAsyncTask extends AsyncTask<String, InstallationAsyncTask.Prog } }; - 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 @@ class InstallationAsyncTask extends AsyncTask<String, InstallationAsyncTask.Prog 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 @@ class InstallationAsyncTask extends AsyncTask<String, InstallationAsyncTask.Prog 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 @@ class InstallationAsyncTask extends AsyncTask<String, InstallationAsyncTask.Prog 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 @@ class InstallationAsyncTask extends AsyncTask<String, InstallationAsyncTask.Prog } } - 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 @@ class InstallationAsyncTask extends AsyncTask<String, InstallationAsyncTask.Prog 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 @@ class InstallationAsyncTask extends AsyncTask<String, InstallationAsyncTask.Prog 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 2d6fca61ce46..51b18d36ad41 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 20a348091dec..ca01d7f839b8 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 40b621c7f569..d898b1e62226 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 56001d82982d..4517efe0934a 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/FooterPreference/res/layout-v31/preference_footer.xml b/packages/SettingsLib/FooterPreference/res/layout-v31/preference_footer.xml index b1276303b801..212ae528a6b9 100644 --- a/packages/SettingsLib/FooterPreference/res/layout-v31/preference_footer.xml +++ b/packages/SettingsLib/FooterPreference/res/layout-v31/preference_footer.xml @@ -46,7 +46,7 @@ android:layout_width="wrap_content" android:layout_height="wrap_content" android:orientation="vertical"> - <com.android.settingslib.widget.LinkTextView + <TextView android:id="@android:id/title" android:layout_width="wrap_content" android:layout_height="wrap_content" diff --git a/packages/SettingsLib/FooterPreference/res/layout/preference_footer.xml b/packages/SettingsLib/FooterPreference/res/layout/preference_footer.xml index 23192b6ce138..d403f9ec8e45 100644 --- a/packages/SettingsLib/FooterPreference/res/layout/preference_footer.xml +++ b/packages/SettingsLib/FooterPreference/res/layout/preference_footer.xml @@ -45,7 +45,7 @@ android:layout_width="wrap_content" android:layout_height="wrap_content" android:orientation="vertical"> - <com.android.settingslib.widget.LinkTextView + <TextView android:id="@android:id/title" android:layout_width="wrap_content" android:layout_height="wrap_content" diff --git a/packages/SettingsLib/FooterPreference/src/com/android/settingslib/widget/FooterPreference.java b/packages/SettingsLib/FooterPreference/src/com/android/settingslib/widget/FooterPreference.java index 3eb6ea98f118..ac306361386e 100644 --- a/packages/SettingsLib/FooterPreference/src/com/android/settingslib/widget/FooterPreference.java +++ b/packages/SettingsLib/FooterPreference/src/com/android/settingslib/widget/FooterPreference.java @@ -19,7 +19,6 @@ package com.android.settingslib.widget; import android.content.Context; import android.text.SpannableString; import android.text.TextUtils; -import android.text.method.LinkMovementMethod; import android.text.style.URLSpan; import android.util.AttributeSet; import android.view.View; @@ -59,10 +58,6 @@ public class FooterPreference extends Preference { public void onBindViewHolder(PreferenceViewHolder holder) { super.onBindViewHolder(holder); TextView title = holder.itemView.findViewById(android.R.id.title); - title.setMovementMethod(new LinkMovementMethod()); - title.setClickable(false); - title.setLongClickable(false); - title.setFocusable(false); if (!TextUtils.isEmpty(mContentDescription)) { title.setContentDescription(mContentDescription); } @@ -86,7 +81,6 @@ public class FooterPreference extends Preference { if (!TextUtils.isEmpty(mLearnMoreContentDescription)) { learnMore.setContentDescription(mLearnMoreContentDescription); } - learnMore.setFocusable(false); } else { learnMore.setVisibility(View.GONE); } @@ -180,6 +174,7 @@ public class FooterPreference extends Preference { if (TextUtils.isEmpty(getKey())) { setKey(KEY_FOOTER); } + setSelectable(false); } /** diff --git a/packages/SettingsLib/SearchWidget/res/values-or/strings.xml b/packages/SettingsLib/SearchWidget/res/values-or/strings.xml index cf824deecd79..322571adc89c 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 000000000000..221d2db00031 --- /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 9d3991119338..cba1a9cf0003 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 24d1171cdeac..23f9a133d012 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 e6201412ca76..c32e94f9a91c 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 65e37e856414..894bc3fd744c 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 f965a34e857b..4ed2e3824df5 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 3fb3f2c58db5..4b2fa6c6f94b 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 a267b46750a1..ffc38bf93820 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 4a1f387daa86..ddadbead06de 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 c3fd0604d50f..42f8782daf8d 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 2e9360e746f2..d21cfad66b70 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 77711cc494a9..c17532b3e811 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 92e7c1ac4978..c7f9ce6fc212 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 014eda90bc11..d7c8ed2a453f 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 d10975de7302..19caaa529286 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 9b8b3b593156..594129b1678e 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 cb6ec174de0b..b913da79bde1 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 c2c14b4f785d..d6dce9960c21 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 91d4a31d0e36..76d1a94bd7aa 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 c2c14b4f785d..d6dce9960c21 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 c2c14b4f785d..d6dce9960c21 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 ebb1d0e596c6..f02d0c5ad376 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 254d41ed133a..49b4b518fbd0 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 447475fb4218..d34beed8b19e 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 2c8a943f4029..a5fa201e9daa 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 019119e6af3e..13ffee7a57c4 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 5e7ee60be380..c50d247fdb3e 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 04df99ff6b75..d958b81a29df 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 88ddd28d38e1..4999bda0212c 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 c7034844b8d9..52575340f11f 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 02fa931fc450..f45c60d45b22 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 b2a9ff3441fe..672bd77d4dce 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 fa51dd25b72c..55e3eafff1df 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 12d97455e6f1..fd29bb5f37bf 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 984df4a27964..dae58549a472 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 1488aea4a110..61d909333507 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 ffa4d4a0aaee..b60e0b70d91b 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 b8a750477c84..40724fda8fbb 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 1552006a68d8..703a0b36bef7 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 22810e9774e7..987af9ca5f89 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 be98ee44cc22..07b04a8f051d 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 f0006d37c4f7..a396600c2644 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 3724ca57b0c8..ccaf1c43feef 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 28211f03348b..370fc4b98cd1 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 635c6872e2fc..a070ad29162f 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 40acb1ac6b58..3cd8583bc201 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 7a50ece104b1..93c432179d82 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 2aced9d253e0..e4d677dbee3a 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 6e7daa715b5a..fbd800c33db7 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 0d6651a7f7a7..5ef979ef8072 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 8111ec023f70..85788103ac95 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 0ae164b00eaa..5abb78265fee 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 7b74da2e4690..fb11d04c31c5 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 451d834351ca..52aa9c6284a5 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 d3dfb62ce0be..7c96e993b258 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 cc6269f0abe1..6fd1d8bacf0a 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 8900fe7ac27a..e965d60105f9 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 d0270a98d121..3bcc65ad1c57 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 5c19a7273677..3d14776ade24 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 14abf05e0b56..f9ee66c3a933 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 4671454941af..f1a24e45aba0 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 073ffbdba2a0..852ed6f26e98 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 8d93b31be90a..cdb364a16a02 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 47a49e7472ee..c647a213d254 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 8d93b31be90a..cdb364a16a02 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 b110c9c29397..778351ede55e 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 6a2da7f8b210..d07e12b3753d 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 b75f548164eb..5140e89e3e78 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 83f880dd2271..b53a7997b189 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 6d4078d7601e..67e20b1447b1 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 ef1e59d92f15..fc2639e0e371 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 333720e80235..44080faf6604 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 2522d7d95943..fbcc2ba30348 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 d6deb2b786a1..8000841d8e7d 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 8d5b87604244..30da8140649c 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 17448320787b..34a324ecb17a 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 c2c34ed02e87..900ac51e18f3 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 a8dcb02bfabf..5bfb3ef6a254 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 592bbae45255..98ed832a0611 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 a219f98d8ba7..a09dc11f23a9 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 3a2d2efb2e5f..ab7c5177b73b 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 3e3db6933e9d..c1748a30c71b 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 2094400ed54f..419f1dac99b1 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 6d5b8e1dd4dd..592e69c39a61 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 d18c0c953f5a..41f399453af0 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 bec3c93077ee..975e6501ef3a 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 16b601c2cb73..119c91b06506 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 bd703963fa43..ca064c9a441d 100644 --- a/packages/SettingsLib/res/values/strings.xml +++ b/packages/SettingsLib/res/values/strings.xml @@ -228,6 +228,13 @@ <!-- Connected devices settings. Message when Bluetooth is connected and active but no battery information, showing remote device status. [CHAR LIMIT=NONE] --> <string name="bluetooth_active_no_battery_level">Active</string> + <!-- Connected device settings. Message when the left-side hearing aid device is active. [CHAR LIMIT=NONE] --> + <string name="bluetooth_hearing_aid_left_active">Active, left ear</string> + <!-- Connected device settings. Message when the right-side hearing aid device is active. [CHAR LIMIT=NONE] --> + <string name="bluetooth_hearing_aid_right_active">Active, right ear</string> + <!-- Connected device settings. Message when the left-side and right-side hearing aids device are active. [CHAR LIMIT=NONE] --> + <string name="bluetooth_hearing_aid_left_and_right_active">Active, left and right ears</string> + <!-- Bluetooth settings. The user-visible string that is used whenever referring to the A2DP profile. --> <string name="bluetooth_profile_a2dp">Media audio</string> <!-- Bluetooth settings. The user-visible string that is used whenever referring to the headset or handsfree profile. --> @@ -347,15 +354,6 @@ <!-- Message for telling the user the kind of BT device being displayed in list. [CHAR LIMIT=30 BACKUP_MESSAGE_ID=5615463912185280812] --> <string name="bluetooth_talkback_bluetooth">Bluetooth</string> - <!-- Message for telling the user the left-side hearing aid device is doing its pairing operation [CHAR LIMIT=NONE] --> - <string name="bluetooth_hearingaid_left_pairing_message">Pairing left hearing aid\u2026</string> - <!-- Message for telling the user the right-side hearing aid device is doing its pairing operation [CHAR LIMIT=NONE] --> - <string name="bluetooth_hearingaid_right_pairing_message">Pairing right hearing aid\u2026</string> - <!-- Bluetooth settings. Message when connected to a left-side Hearing Aid device, showing remote device battery level. [CHAR LIMIT=NONE] --> - <string name="bluetooth_hearingaid_left_battery_level">Left - <xliff:g id="battery_level_as_percentage">%1$s</xliff:g> battery</string> - <!-- Bluetooth settings. Message when connected to a right-side Hearing Aid device, showing remote device battery level. [CHAR LIMIT=NONE] --> - <string name="bluetooth_hearingaid_right_battery_level">Right - <xliff:g id="battery_level_as_percentage">%1$s</xliff:g> battery</string> - <!-- Content description of the WIFI signal when WIFI is disabled for accessibility (not shown on the screen). [CHAR LIMIT=NONE] --> <string name="accessibility_wifi_off">Wifi off.</string> <!-- Content description of the WIFI signal when no signal for accessibility (not shown on the screen). [CHAR LIMIT=NONE] --> @@ -1038,23 +1036,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 +1325,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 +1563,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 e4efae2f1a36..3a4a8d27b2f3 100644 --- a/packages/SettingsLib/src/com/android/settingslib/RestrictedPreferenceHelper.java +++ b/packages/SettingsLib/src/com/android/settingslib/RestrictedPreferenceHelper.java @@ -23,12 +23,15 @@ import static com.android.settingslib.RestrictedLockUtils.EnforcedAdmin; 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 @@ public class RestrictedPreferenceHelper { 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 @@ public class RestrictedPreferenceHelper { } } + @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 19114cf147e4..f639022f222d 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.TetheringManager; 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.ServiceState; 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 @@ public class Utils { 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 @@ public class Utils { 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 389892ed15e4..62c83cf04a4f 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 @@ public class BluetoothEventManager { || 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 3d91c5aceeed..2a28891e9158 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 @@ public class CachedBluetoothDevice implements Comparable<CachedBluetoothDevice> 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 @@ public class CachedBluetoothDevice implements Comparable<CachedBluetoothDevice> 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 e203cbaa3da5..19df1e9c0730 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 @@ public class LeAudioProfile implements LocalBluetoothProfile { 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 e7a6b327bacd..31cc6a4ba412 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 class LocalBluetoothAdapter { } 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 c61f8a9c3b53..be420ac8bd24 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.TelephonyCallback; 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 @@ public class ConnectivitySubsystemsRecoveryManager { 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 d01f2b42f338..94d90a8eb028 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 @@ public class UserIconDrawable extends Drawable implements Drawable.Callback { @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 @@ public class UserIconDrawable extends Drawable implements Drawable.Callback { @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 0cb2c0b22a4c..63a9f0c5c7f4 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 @@ class AvatarPhotoController { 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 @@ class AvatarPhotoController { 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 @@ class AvatarPhotoController { 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 @@ class AvatarPhotoController { 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 69f1c17f97b1..2c1d5da5e941 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 @@ public class ThreadUtils { 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/res/layout/preference_footer.xml b/packages/SettingsLib/tests/robotests/res/layout/preference_footer.xml index c47bff7104ba..766efa829778 100644 --- a/packages/SettingsLib/tests/robotests/res/layout/preference_footer.xml +++ b/packages/SettingsLib/tests/robotests/res/layout/preference_footer.xml @@ -23,32 +23,46 @@ android:paddingStart="?android:attr/listPreferredItemPaddingStart" android:paddingEnd="?android:attr/listPreferredItemPaddingEnd" android:background="?android:attr/selectableItemBackground" + android:orientation="vertical" android:clipToPadding="false"> <LinearLayout - android:id="@+id/icon_container" + android:id="@+id/icon_frame" android:layout_width="wrap_content" android:layout_height="wrap_content" - android:minWidth="60dp" + android:minWidth="56dp" android:gravity="start|top" android:orientation="horizontal" android:paddingEnd="12dp" - android:paddingTop="20dp" + android:paddingTop="16dp" android:paddingBottom="4dp"> <ImageView android:id="@android:id/icon" android:layout_width="wrap_content" - android:layout_height="wrap_content" /> + android:layout_height="wrap_content"/> </LinearLayout> - <com.android.settingslib.widget.LinkTextView - android:id="@android:id/title" + <LinearLayout android:layout_width="wrap_content" android:layout_height="wrap_content" - android:paddingBottom="16dp" - android:paddingTop="16dp" - android:maxLines="10" - android:textColor="?android:attr/textColorSecondary" - android:ellipsize="marquee" /> + android:orientation="vertical"> + <TextView + android:id="@android:id/title" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:paddingTop="16dp" + android:paddingBottom="8dp" + android:textColor="?android:attr/textColorSecondary" + android:ellipsize="marquee" /> + + <com.android.settingslib.widget.LinkTextView + android:id="@+id/settingslib_learn_more" + android:text="@string/settingslib_learn_more_text" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:clickable="true" + android:visibility="gone" + style="@style/TextAppearance.Footer.Title.SettingsLib"/> + </LinearLayout> </LinearLayout> 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 852ac5ca6abe..7b94492cef4f 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 @@ public class BluetoothEventManagerTest { 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 @@ public class BluetoothEventManagerTest { 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 @@ public class BluetoothEventManagerTest { 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 @@ public class BluetoothEventManagerTest { 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 000000000000..ca53a187d6f8 --- /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/SettingsLib/tests/robotests/src/com/android/settingslib/widget/FooterPreferenceTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/widget/FooterPreferenceTest.java index 3b18c57e28fa..61a28aab061f 100644 --- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/widget/FooterPreferenceTest.java +++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/widget/FooterPreferenceTest.java @@ -19,7 +19,6 @@ package com.android.settingslib.widget; import static com.google.common.truth.Truth.assertThat; import android.content.Context; -import android.text.method.LinkMovementMethod; import android.view.LayoutInflater; import android.widget.TextView; @@ -46,17 +45,6 @@ public class FooterPreferenceTest { } @Test - public void bindPreference_shouldLinkifyContent() { - final PreferenceViewHolder holder = PreferenceViewHolder.createInstanceForTests( - LayoutInflater.from(mContext).inflate(R.layout.preference_footer, null)); - - mFooterPreference.onBindViewHolder(holder); - - assertThat(((TextView) holder.findViewById(android.R.id.title)).getMovementMethod()) - .isInstanceOf(LinkMovementMethod.class); - } - - @Test public void setSummary_summarySet_shouldSetAsTitle() { mFooterPreference.setSummary("summary"); diff --git a/packages/SettingsProvider/res/values-or/strings.xml b/packages/SettingsProvider/res/values-or/strings.xml index 486d8ffaa500..85add41b1ee1 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 f49e209c09a1..eaf0dcb9b4e7 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 @@ public class SettingsProviderTest extends BaseSettingsProviderTest { 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 @@ public class SettingsProviderTest extends BaseSettingsProviderTest { // 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 e7765e6d01e9..955aee940513 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 e24b2d6c6aa9..4b45cc338a6a 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 9722b1fe2d2e..c8e78c3df5be 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/plugin/src/com/android/systemui/plugins/ActivityStarter.java b/packages/SystemUI/plugin/src/com/android/systemui/plugins/ActivityStarter.java index 6d088f090bcd..1fec3314a13e 100644 --- a/packages/SystemUI/plugin/src/com/android/systemui/plugins/ActivityStarter.java +++ b/packages/SystemUI/plugin/src/com/android/systemui/plugins/ActivityStarter.java @@ -17,6 +17,7 @@ package com.android.systemui.plugins; import android.annotation.Nullable; import android.app.PendingIntent; import android.content.Intent; +import android.os.UserHandle; import android.view.View; import com.android.systemui.animation.ActivityLaunchAnimator; @@ -70,6 +71,9 @@ public interface ActivityStarter { void startActivity(Intent intent, boolean dismissShade, @Nullable ActivityLaunchAnimator.Controller animationController, boolean showOverLockscreenWhenLocked); + void startActivity(Intent intent, boolean dismissShade, + @Nullable ActivityLaunchAnimator.Controller animationController, + boolean showOverLockscreenWhenLocked, UserHandle userHandle); void startActivity(Intent intent, boolean onlyProvisioned, boolean dismissShade); void startActivity(Intent intent, boolean dismissShade, Callback callback); void postStartActivityDismissingKeyguard(Intent intent, int delay); diff --git a/packages/SystemUI/res-keyguard/values-it/strings.xml b/packages/SystemUI/res-keyguard/values-it/strings.xml index 06db7b7dfd60..f912a28d0342 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 c3486bbf62d9..a8d8f349ca1e 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 8d205c14144d..9a6f5edae5ec 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 9b43cf64f116..779ab816d925 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 1b750f8959b9..5fbc42b245b8 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 05c635833441..0599e239a9ee 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 ec74ee1fcbf1..3e2e4f055b14 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 1ed75537059a..d81b518d2a9f 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 91d81a2b0b2f..cb63300f819b 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 3900ea56dda3..76fe58c29852 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 eeb37c7b062d..20747fad021b 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 812277634d09..5aa608084510 100644 --- a/packages/SystemUI/res/layout/ongoing_privacy_chip.xml +++ b/packages/SystemUI/res/layout/ongoing_privacy_chip.xml @@ -22,7 +22,10 @@ android:layout_height="match_parent" android:layout_width="wrap_content" android:layout_gravity="center_vertical|end" - android:focusable="true" > + android:focusable="true" + android:clipChildren="false" + android:clipToPadding="false" + > <LinearLayout android:id="@+id/icons_container" diff --git a/packages/SystemUI/res/layout/system_event_animation_window.xml b/packages/SystemUI/res/layout/system_event_animation_window.xml index c92dec9dd643..e6868b34df02 100644 --- a/packages/SystemUI/res/layout/system_event_animation_window.xml +++ b/packages/SystemUI/res/layout/system_event_animation_window.xml @@ -19,17 +19,7 @@ android:layout_width="match_parent" android:layout_height="match_parent" android:layout_gravity="center_vertical|end" - android:paddingTop="@dimen/status_bar_padding_top" - android:paddingEnd="8dp" + android:clipChildren="false" + android:clipToPadding="false" > - - <ImageView - android:id="@+id/dot_view" - android:layout_width="10dp" - android:layout_height="10dp" - android:layout_gravity="center_vertical|end" - android:src="@drawable/system_animation_ongoing_dot" - android:visibility="invisible" - /> - </FrameLayout>
\ 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 c0fdf689cfc2..8d09d7621042 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 43ad0057d2ba..83c018494a92 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 5ec5e9b537f0..24e36fb5866f 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 00f7790e384d..7bb97a78d214 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 a1956b30c54c..a796a201834a 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 2019e9dbcb8a..cd6b9cc147b5 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 c10a36d66373..0380a764e179 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 a10750401a05..f56e57d4a6cf 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 b5040e959a34..2730b4cc3ebf 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 b0691fe6b5b0..00973eee5674 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 da4cba76a427..975f4e0f1f53 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 e93fc2937913..ee9a04fe2dd6 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 bf460fe05c6b..43027b833267 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 6197b3fbae0c..60bcecb93d8b 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 dc0d98bc7caf..17a54c2ad7c9 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 fcbe0a6927aa..5544a9597fae 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 2e6514a3f77d..9a204eb5d296 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 fcbe0a6927aa..5544a9597fae 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 fcbe0a6927aa..5544a9597fae 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 f05e75b187e4..052f175280ff 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 4363ce9c298f..57996ee26e6f 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 0e7be44a61e0..f4a8cf7f673e 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 0c9d46ed868e..b6d266c394aa 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 90d24e507ba2..768c2020e5b6 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 99e214b77fe2..3e76c46241f8 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 5aca1cea9f7c..3257d8b87385 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 1a599b5ecaf7..e91e55dd4d37 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 1465bdbc508b..33194aae5042 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 5faa3df65171..52a55e7ab7fa 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 763d39de4913..497029e8927e 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 27e5091cdc59..d7b9f327d821 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 d3905e7bb820..77cf81422a41 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 3b94d8f15d90..f256bc14b63f 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 488aa7674805..a4e3b82b264b 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 0913166cc1eb..c9ce287484ab 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 cddb8f81fc09..78d2ecf38a18 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 ed125cd306e8..9b0f917759d3 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 f88605a90adf..7dcde9cf4f5c 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 b946344c8af5..956826bb5e37 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 31d760611843..7ecdfd93b2c4 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 c8abf951d255..85283de03b1c 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 78e6c8439f12..9e527e4a04c6 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 e10f5d393787..ce0ca0e62f2f 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 ba6ef05d7ba1..8705e7105385 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 a31ab6d3f0bf..6187f3a27c6c 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 204e3d92a3a6..3343bcfa0a53 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 6bcfa0e91678..547d250895ef 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 286cdecc6c4b..5e79f75557be 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 ffa0e58b88b5..0bde00b24b63 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 6aeb7e75e0da..e7ccae0997c6 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 4abfe1b0bb48..b136674ea9d7 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 2ec0073808b2..721368a04ccd 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 06270d71427e..b34a312abac7 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 4a4f1a16f517..b1b2ceb9b77a 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 5ccf52890432..745454cc6e9b 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 471bf14152d8..bfe29aa5a26e 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 4b96d5d660ee..3a638b1e5098 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 047f99f130b7..0f49b75a06db 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 0dca918eccce..ed1fbbccdbe0 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 faa206224214..beda96084ddd 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 5d61dfe567d2..a2f94fc657ca 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 d9bb15b66a11..adc33a7ecd11 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 73ef834df64d..79f33fb5fcc1 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 d9bb15b66a11..adc33a7ecd11 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 ff409d33fc94..f57aa7195b84 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 a79c247b882c..de09d7680330 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 ffaa4bfccf92..cdb0896a3fab 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 2c2a7c881ff6..5e29c9399777 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 6996d56f2861..cf9cb1c84212 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 bea8d835c39b..fcf886818d42 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 f373eea9d8e3..1025552b613d 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 638ba9f7e4f2..ed89872724ba 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 931f6343b7df..2f184a1a7ee2 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 c56ba7b6b1ce..740697ba98af 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 f267088ea203..bdd704936594 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 e856294f2ed3..cd40c79f15bc 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 6ef8f5086535..222da19a7254 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 9072db444912..120d87077454 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 b518c603458d..4d5655c191d6 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 0f56057ef082..170d582f8583 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 fa9af2e1c77f..87ea462dfb25 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 35760212155d..cb1cbddfa0a9 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 0cead719b0a4..1128b297a56f 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 a5609eb8a6d7..068127b17e98 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 0610b5917f46..b5671e6df9e7 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 860085974d4f..718d5e1f7e5e 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 0206a9e30360..dcb74b30a6cd 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 98e7fc40e7ab..f26ef0efa126 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 1edaaadfb433..49fc8482712a 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 a0a876825a6f..9ea361892b32 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 52ec51629116..8f4e11527d95 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 9f2f1c1978c6..6dc6214fec65 100644 --- a/packages/SystemUI/res/values/strings.xml +++ b/packages/SystemUI/res/values/strings.xml @@ -1193,10 +1193,7 @@ <string name="wallet_lockscreen_settings_label">Lock screen settings</string> <!-- QR Code Scanner label, title [CHAR LIMIT=32] --> - <string name="qr_code_scanner_title">QR code</string> - - <!-- QR Code Scanner description [CHAR LIMIT=NONE] --> - <string name="qr_code_scanner_description">Tap to scan</string> + <string name="qr_code_scanner_title">Scan QR code</string> <!-- Name of the work status bar icon. --> <string name="status_bar_work">Work profile</string> @@ -2187,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 3ae21e08005d..f5c1382b9ae9 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/shared/src/com/android/systemui/flags/Flag.kt b/packages/SystemUI/shared/src/com/android/systemui/flags/Flag.kt index 6ad91612f99b..19a53091b35c 100644 --- a/packages/SystemUI/shared/src/com/android/systemui/flags/Flag.kt +++ b/packages/SystemUI/shared/src/com/android/systemui/flags/Flag.kt @@ -24,6 +24,7 @@ import android.os.Parcelable interface Flag<T> { val id: Int + val teamfood: Boolean } interface ParcelableFlag<T> : Flag<T>, Parcelable { @@ -44,7 +45,8 @@ interface SysPropFlag<T> : Flag<T> { data class BooleanFlag @JvmOverloads constructor( override val id: Int, - override val default: Boolean = false + override val default: Boolean = false, + override val teamfood: Boolean = false ) : ParcelableFlag<Boolean> { companion object { @@ -66,20 +68,25 @@ data class BooleanFlag @JvmOverloads constructor( } } -data class ResourceBooleanFlag constructor( +data class ResourceBooleanFlag @JvmOverloads constructor( override val id: Int, - @BoolRes override val resourceId: Int + @BoolRes override val resourceId: Int, + override val teamfood: Boolean = false ) : ResourceFlag<Boolean> -data class SysPropBooleanFlag constructor( +data class SysPropBooleanFlag @JvmOverloads constructor( override val id: Int, override val name: String, override val default: Boolean = false -) : SysPropFlag<Boolean> +) : SysPropFlag<Boolean> { + // TODO(b/223379190): Teamfood not supported for sysprop flags yet. + override val teamfood: Boolean = false +} data class StringFlag @JvmOverloads constructor( override val id: Int, - override val default: String = "" + override val default: String = "", + override val teamfood: Boolean = false ) : ParcelableFlag<String> { companion object { @JvmField @@ -100,14 +107,16 @@ data class StringFlag @JvmOverloads constructor( } } -data class ResourceStringFlag constructor( +data class ResourceStringFlag @JvmOverloads constructor( override val id: Int, - @StringRes override val resourceId: Int + @StringRes override val resourceId: Int, + override val teamfood: Boolean = false ) : ResourceFlag<String> data class IntFlag @JvmOverloads constructor( override val id: Int, - override val default: Int = 0 + override val default: Int = 0, + override val teamfood: Boolean = false ) : ParcelableFlag<Int> { companion object { @@ -129,14 +138,16 @@ data class IntFlag @JvmOverloads constructor( } } -data class ResourceIntFlag constructor( +data class ResourceIntFlag @JvmOverloads constructor( override val id: Int, - @IntegerRes override val resourceId: Int + @IntegerRes override val resourceId: Int, + override val teamfood: Boolean = false ) : ResourceFlag<Int> data class LongFlag @JvmOverloads constructor( override val id: Int, - override val default: Long = 0 + override val default: Long = 0, + override val teamfood: Boolean = false ) : ParcelableFlag<Long> { companion object { @@ -160,7 +171,8 @@ data class LongFlag @JvmOverloads constructor( data class FloatFlag @JvmOverloads constructor( override val id: Int, - override val default: Float = 0f + override val default: Float = 0f, + override val teamfood: Boolean = false ) : ParcelableFlag<Float> { companion object { @@ -182,14 +194,16 @@ data class FloatFlag @JvmOverloads constructor( } } -data class ResourceFloatFlag constructor( +data class ResourceFloatFlag @JvmOverloads constructor( override val id: Int, - override val resourceId: Int + override val resourceId: Int, + override val teamfood: Boolean = false ) : ResourceFlag<Int> data class DoubleFlag @JvmOverloads constructor( override val id: Int, - override val default: Double = 0.0 + override val default: Double = 0.0, + override val teamfood: Boolean = false ) : ParcelableFlag<Double> { companion object { diff --git a/packages/SystemUI/shared/src/com/android/systemui/flags/FlagManager.kt b/packages/SystemUI/shared/src/com/android/systemui/flags/FlagManager.kt index 149f6e8e7e9e..26e40e1ecad3 100644 --- a/packages/SystemUI/shared/src/com/android/systemui/flags/FlagManager.kt +++ b/packages/SystemUI/shared/src/com/android/systemui/flags/FlagManager.kt @@ -64,7 +64,7 @@ class FlagManager constructor( intent.setPackage(RECEIVING_PACKAGE) return CallbackToFutureAdapter.getFuture { - completer: CallbackToFutureAdapter.Completer<Any?> -> + completer: CallbackToFutureAdapter.Completer<Collection<Flag<*>>> -> context.sendOrderedBroadcast(intent, null, object : BroadcastReceiver() { override fun onReceive(context: Context, intent: Intent) { @@ -79,7 +79,7 @@ class FlagManager constructor( } }, null, Activity.RESULT_OK, "extra data", null) "QueryingFlags" - } as ListenableFuture<Collection<Flag<*>>> + } } /** diff --git a/packages/SystemUI/src-debug/com/android/systemui/flags/FlagsModule.kt b/packages/SystemUI/src-debug/com/android/systemui/flags/FlagsModule.kt index adfc87241460..256028417a1d 100644 --- a/packages/SystemUI/src-debug/com/android/systemui/flags/FlagsModule.kt +++ b/packages/SystemUI/src-debug/com/android/systemui/flags/FlagsModule.kt @@ -19,11 +19,12 @@ package com.android.systemui.flags import android.content.Context import android.os.Handler import com.android.systemui.dagger.qualifiers.Main +import com.android.systemui.flags.FeatureFlagsDebug.ALL_FLAGS import com.android.systemui.util.settings.SettingsUtilModule import dagger.Binds import dagger.Module import dagger.Provides -import java.util.function.Supplier +import javax.inject.Named @Module(includes = [ SettingsUtilModule::class @@ -42,6 +43,7 @@ abstract class FlagsModule { @JvmStatic @Provides - fun providesFlagCollector(): Supplier<Map<Int, Flag<*>>>? = null + @Named(ALL_FLAGS) + fun providesAllFlags(): Map<Int, Flag<*>> = Flags.collectFlags() } }
\ No newline at end of file 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 000000000000..497d81f6bdc5 --- /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 b6910961bcb4..8c3e066849b9 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.keyguard.dagger.KeyguardBouncerScope; 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 @@ public class KeyguardHostViewController extends ViewController<KeyguardHostView> private ActivityStarter.OnDismissAction mDismissAction; private Runnable mCancelAction; + private int mTranslationY; private final KeyguardUpdateMonitorCallback mUpdateCallback = new KeyguardUpdateMonitorCallback() { @@ -322,12 +322,14 @@ public class KeyguardHostViewController extends ViewController<KeyguardHostView> /** * 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 @@ public class KeyguardHostViewController extends ViewController<KeyguardHostView> 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 362fbed7055a..46a883194e25 100644 --- a/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainer.java +++ b/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainer.java @@ -152,6 +152,7 @@ public class KeyguardSecurityContainer extends FrameLayout { 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 @@ public class KeyguardSecurityContainer extends FrameLayout { 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 1ef6dea4e680..3858f9cd7a82 100644 --- a/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java +++ b/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java @@ -326,7 +326,6 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab 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 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab 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 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab // 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 74659f71eb1f..e36e984380e2 100644 --- a/packages/SystemUI/src/com/android/keyguard/LockIconViewController.java +++ b/packages/SystemUI/src/com/android/keyguard/LockIconViewController.java @@ -211,6 +211,23 @@ public class LockIconViewController extends ViewController<LockIconView> impleme 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/ActivityStarterDelegate.java b/packages/SystemUI/src/com/android/systemui/ActivityStarterDelegate.java index 5bd620e873b0..7af6f6677f3f 100644 --- a/packages/SystemUI/src/com/android/systemui/ActivityStarterDelegate.java +++ b/packages/SystemUI/src/com/android/systemui/ActivityStarterDelegate.java @@ -16,6 +16,7 @@ package com.android.systemui; import android.app.PendingIntent; import android.content.Intent; +import android.os.UserHandle; import android.view.View; import androidx.annotation.Nullable; @@ -100,6 +101,15 @@ public class ActivityStarterDelegate implements ActivityStarter { } @Override + public void startActivity(Intent intent, boolean dismissShade, + @Nullable ActivityLaunchAnimator.Controller animationController, + boolean showOverLockscreenWhenLocked, UserHandle userHandle) { + mActualStarterOptionalLazy.get().ifPresent( + starter -> starter.startActivity(intent, dismissShade, animationController, + showOverLockscreenWhenLocked, userHandle)); + } + + @Override public void startActivity(Intent intent, boolean onlyProvisioned, boolean dismissShade) { mActualStarterOptionalLazy.get().ifPresent( starter -> starter.startActivity(intent, onlyProvisioned, dismissShade)); diff --git a/packages/SystemUI/src/com/android/systemui/ScreenDecorHwcLayer.kt b/packages/SystemUI/src/com/android/systemui/ScreenDecorHwcLayer.kt index 4b868622ce58..498e71546bed 100644 --- a/packages/SystemUI/src/com/android/systemui/ScreenDecorHwcLayer.kt +++ b/packages/SystemUI/src/com/android/systemui/ScreenDecorHwcLayer.kt @@ -119,9 +119,13 @@ class ScreenDecorHwcLayer(context: Context, displayDecorationSupport: DisplayDec 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/ScreenDecorations.java b/packages/SystemUI/src/com/android/systemui/ScreenDecorations.java index ae41cae10bba..2f5292cec909 100644 --- a/packages/SystemUI/src/com/android/systemui/ScreenDecorations.java +++ b/packages/SystemUI/src/com/android/systemui/ScreenDecorations.java @@ -37,13 +37,11 @@ import android.content.pm.ActivityInfo; import android.content.res.ColorStateList; import android.content.res.Configuration; import android.content.res.Resources; -import android.content.res.TypedArray; import android.graphics.Color; import android.graphics.Matrix; import android.graphics.Paint; import android.graphics.Path; import android.graphics.PixelFormat; -import android.graphics.Point; import android.graphics.Rect; import android.graphics.drawable.Drawable; import android.hardware.display.DisplayManager; @@ -53,14 +51,12 @@ import android.os.Handler; import android.os.SystemProperties; import android.os.UserHandle; import android.provider.Settings.Secure; -import android.util.DisplayMetrics; -import android.util.DisplayUtils; import android.util.Log; +import android.util.Size; import android.view.DisplayCutout; import android.view.DisplayCutout.BoundsPosition; import android.view.Gravity; import android.view.LayoutInflater; -import android.view.RoundedCorners; import android.view.View; import android.view.View.OnLayoutChangeListener; import android.view.ViewGroup; @@ -81,6 +77,7 @@ import com.android.systemui.decor.DecorProviderFactory; import com.android.systemui.decor.DecorProviderKt; import com.android.systemui.decor.OverlayWindow; import com.android.systemui.decor.PrivacyDotDecorProviderFactory; +import com.android.systemui.decor.RoundedCornerResDelegate; import com.android.systemui.qs.SettingObserver; import com.android.systemui.settings.UserTracker; import com.android.systemui.statusbar.events.PrivacyDotViewController; @@ -139,11 +136,7 @@ public class ScreenDecorations extends CoreStartable implements Tunable , Dumpab // corners. for now it is only supposed when reading the intrinsic size from the drawables with // mIsRoundedCornerMultipleRadius is set @VisibleForTesting - protected Point mRoundedDefault = new Point(0, 0); - @VisibleForTesting - protected Point mRoundedDefaultTop = new Point(0, 0); - @VisibleForTesting - protected Point mRoundedDefaultBottom = new Point(0, 0); + protected RoundedCornerResDelegate mRoundedCornerResDelegate; @VisibleForTesting protected OverlayWindow[] mOverlays = null; @Nullable @@ -152,17 +145,12 @@ public class ScreenDecorations extends CoreStartable implements Tunable , Dumpab ViewGroup mScreenDecorHwcWindow; @VisibleForTesting ScreenDecorHwcLayer mScreenDecorHwcLayer; - private float mDensity; private WindowManager mWindowManager; private int mRotation; private SettingObserver mColorInversionSetting; private DelayableExecutor mExecutor; private Handler mHandler; boolean mPendingRotationChange; - private boolean mIsRoundedCornerMultipleRadius; - private Drawable mRoundedCornerDrawable; - private Drawable mRoundedCornerDrawableTop; - private Drawable mRoundedCornerDrawableBottom; @VisibleForTesting String mDisplayUniqueId; private int mTintColor = Color.BLACK; @@ -302,7 +290,8 @@ public class ScreenDecorations extends CoreStartable implements Tunable , Dumpab private void startOnScreenDecorationsThread() { mRotation = mContext.getDisplay().getRotation(); mDisplayUniqueId = mContext.getDisplay().getUniqueId(); - mIsRoundedCornerMultipleRadius = isRoundedCornerMultipleRadius(mContext, mDisplayUniqueId); + mRoundedCornerResDelegate = new RoundedCornerResDelegate(mContext.getResources(), + mDisplayUniqueId); mWindowManager = mContext.getSystemService(WindowManager.class); mDisplayManager = mContext.getSystemService(DisplayManager.class); mHwcScreenDecorationSupport = mContext.getDisplay().getDisplayDecorationSupport(); @@ -359,8 +348,7 @@ public class ScreenDecorations extends CoreStartable implements Tunable , Dumpab final String newUniqueId = mContext.getDisplay().getUniqueId(); if (!Objects.equals(newUniqueId, mDisplayUniqueId)) { mDisplayUniqueId = newUniqueId; - mIsRoundedCornerMultipleRadius = - isRoundedCornerMultipleRadius(mContext, mDisplayUniqueId); + mRoundedCornerResDelegate.reloadAll(newUniqueId); final DisplayDecorationSupport newScreenDecorationSupport = mContext.getDisplay().getDisplayDecorationSupport(); // When the value of mSupportHwcScreenDecoration is changed, re-setup the whole @@ -457,9 +445,6 @@ public class ScreenDecorations extends CoreStartable implements Tunable , Dumpab if (mIsRegistered) { return; } - DisplayMetrics metrics = new DisplayMetrics(); - mContext.getDisplay().getMetrics(metrics); - mDensity = metrics.density; mMainExecutor.execute(() -> mTunerService.addTunable(this, SIZE)); @@ -606,8 +591,8 @@ public class ScreenDecorations extends CoreStartable implements Tunable , Dumpab mScreenDecorHwcWindow.addView(mScreenDecorHwcLayer, new FrameLayout.LayoutParams( MATCH_PARENT, MATCH_PARENT, Gravity.TOP | Gravity.START)); mWindowManager.addView(mScreenDecorHwcWindow, getHwcWindowLayoutParams()); - updateRoundedCornerSize(mRoundedDefault, mRoundedDefaultTop, mRoundedDefaultBottom); - updateRoundedCornerImageView(); + updateHwLayerRoundedCornerSize(); + updateHwLayerRoundedCornerDrawable(); mScreenDecorHwcWindow.getViewTreeObserver().addOnPreDrawListener( new ValidatingPreDrawListener(mScreenDecorHwcWindow)); } @@ -640,7 +625,9 @@ public class ScreenDecorations extends CoreStartable implements Tunable , Dumpab // update rounded corner view rotation updateRoundedCornerView(pos, R.id.left, cutout); updateRoundedCornerView(pos, R.id.right, cutout); - updateRoundedCornerSize(mRoundedDefault, mRoundedDefaultTop, mRoundedDefaultBottom); + updateRoundedCornerSize( + mRoundedCornerResDelegate.getTopRoundedSize(), + mRoundedCornerResDelegate.getBottomRoundedSize()); updateRoundedCornerImageView(); // update cutout view rotation @@ -844,7 +831,6 @@ public class ScreenDecorations extends CoreStartable implements Tunable , Dumpab public void dump(@NonNull FileDescriptor fd, @NonNull PrintWriter pw, @NonNull String[] args) { pw.println("ScreenDecorations state:"); pw.println(" DEBUG_DISABLE_SCREEN_DECORATIONS:" + DEBUG_DISABLE_SCREEN_DECORATIONS); - pw.println(" mIsRoundedCornerMultipleRadius:" + mIsRoundedCornerMultipleRadius); pw.println(" mIsPrivacyDotEnabled:" + isPrivacyDotEnabled()); pw.println(" mPendingRotationChange:" + mPendingRotationChange); if (mHwcScreenDecorationSupport != null) { @@ -862,16 +848,12 @@ public class ScreenDecorations extends CoreStartable implements Tunable , Dumpab } else { pw.println(" mScreenDecorHwcLayer: null"); } - pw.println(" mRoundedDefault(x,y)=(" + mRoundedDefault.x + "," + mRoundedDefault.y + ")"); - pw.println(" mRoundedDefaultTop(x,y)=(" + mRoundedDefaultTop.x + "," + mRoundedDefaultTop.y - + ")"); - pw.println(" mRoundedDefaultBottom(x,y)=(" + mRoundedDefaultBottom.x + "," - + mRoundedDefaultBottom.y + ")"); pw.println(" mOverlays(left,top,right,bottom)=(" + (mOverlays != null && mOverlays[BOUNDS_POSITION_LEFT] != null) + "," + (mOverlays != null && mOverlays[BOUNDS_POSITION_TOP] != null) + "," + (mOverlays != null && mOverlays[BOUNDS_POSITION_RIGHT] != null) + "," + (mOverlays != null && mOverlays[BOUNDS_POSITION_BOTTOM] != null) + ")"); + mRoundedCornerResDelegate.dump(fd, pw, args); } private void updateOrientation() { @@ -912,119 +894,18 @@ public class ScreenDecorations extends CoreStartable implements Tunable , Dumpab // upgrading all of the configs to contain (width, height) pairs. Instead assume that a // device configured using the single integer config value is okay with drawing the corners // as a square - final int newRoundedDefault = RoundedCorners.getRoundedCornerRadius( - mContext.getResources(), mDisplayUniqueId); - final int newRoundedDefaultTop = RoundedCorners.getRoundedCornerTopRadius( - mContext.getResources(), mDisplayUniqueId); - final int newRoundedDefaultBottom = RoundedCorners.getRoundedCornerBottomRadius( - mContext.getResources(), mDisplayUniqueId); - - final boolean changed = mRoundedDefault.x != newRoundedDefault - || mRoundedDefaultTop.x != newRoundedDefaultTop - || mRoundedDefaultBottom.x != newRoundedDefaultBottom; - - if (changed) { - // If config_roundedCornerMultipleRadius set as true, ScreenDecorations respect the - // (width, height) size of drawable/rounded.xml instead of rounded_corner_radius - if (mIsRoundedCornerMultipleRadius) { - mRoundedDefault.set(mRoundedCornerDrawable.getIntrinsicWidth(), - mRoundedCornerDrawable.getIntrinsicHeight()); - mRoundedDefaultTop.set(mRoundedCornerDrawableTop.getIntrinsicWidth(), - mRoundedCornerDrawableTop.getIntrinsicHeight()); - mRoundedDefaultBottom.set(mRoundedCornerDrawableBottom.getIntrinsicWidth(), - mRoundedCornerDrawableBottom.getIntrinsicHeight()); - } else { - mRoundedDefault.set(newRoundedDefault, newRoundedDefault); - mRoundedDefaultTop.set(newRoundedDefaultTop, newRoundedDefaultTop); - mRoundedDefaultBottom.set(newRoundedDefaultBottom, newRoundedDefaultBottom); - } + final Size oldRoundedDefaultTop = mRoundedCornerResDelegate.getTopRoundedSize(); + final Size oldRoundedDefaultBottom = mRoundedCornerResDelegate.getBottomRoundedSize(); + mRoundedCornerResDelegate.reloadAll(mDisplayUniqueId); + final Size newRoundedDefaultTop = mRoundedCornerResDelegate.getTopRoundedSize(); + final Size newRoundedDefaultBottom = mRoundedCornerResDelegate.getBottomRoundedSize(); + + if (oldRoundedDefaultTop.getWidth() != newRoundedDefaultTop.getWidth() + || oldRoundedDefaultBottom.getWidth() != newRoundedDefaultBottom.getWidth()) { onTuningChanged(SIZE, null); } } - /** - * Gets whether the rounded corners are multiple radii for current display. - * - * Loads the default config {@link R.bool#config_roundedCornerMultipleRadius} if - * {@link com.android.internal.R.array#config_displayUniqueIdArray} is not set. - */ - private static boolean isRoundedCornerMultipleRadius(Context context, String displayUniqueId) { - final Resources res = context.getResources(); - final int index = DisplayUtils.getDisplayUniqueIdConfigIndex(res, displayUniqueId); - final TypedArray array = res.obtainTypedArray( - R.array.config_roundedCornerMultipleRadiusArray); - boolean isMultipleRadius; - if (index >= 0 && index < array.length()) { - isMultipleRadius = array.getBoolean(index, false); - } else { - isMultipleRadius = res.getBoolean(R.bool.config_roundedCornerMultipleRadius); - } - array.recycle(); - return isMultipleRadius; - } - - /** - * Gets the rounded corner drawable for current display. - * - * Loads the default config {@link R.drawable#rounded} if - * {@link com.android.internal.R.array#config_displayUniqueIdArray} is not set. - */ - private static Drawable getRoundedCornerDrawable(Context context, String displayUniqueId) { - final Resources res = context.getResources(); - final int index = DisplayUtils.getDisplayUniqueIdConfigIndex(res, displayUniqueId); - final TypedArray array = res.obtainTypedArray(R.array.config_roundedCornerDrawableArray); - Drawable drawable; - if (index >= 0 && index < array.length()) { - drawable = array.getDrawable(index); - } else { - drawable = context.getDrawable(R.drawable.rounded); - } - array.recycle(); - return drawable; - } - - /** - * Gets the rounded corner top drawable for current display. - * - * Loads the default config {@link R.drawable#rounded_corner_top} if - * {@link com.android.internal.R.array#config_displayUniqueIdArray} is not set. - */ - private static Drawable getRoundedCornerTopDrawable(Context context, String displayUniqueId) { - final Resources res = context.getResources(); - final int index = DisplayUtils.getDisplayUniqueIdConfigIndex(res, displayUniqueId); - final TypedArray array = res.obtainTypedArray(R.array.config_roundedCornerTopDrawableArray); - Drawable drawable; - if (index >= 0 && index < array.length()) { - drawable = array.getDrawable(index); - } else { - drawable = context.getDrawable(R.drawable.rounded_corner_top); - } - array.recycle(); - return drawable; - } - - /** - * Gets the rounded corner bottom drawable for current display. - * - * Loads the default config {@link R.drawable#rounded_corner_bottom} if - * {@link com.android.internal.R.array#config_displayUniqueIdArray} is not set. - */ - private static Drawable getRoundedCornerBottomDrawable( - Context context, String displayUniqueId) { - final Resources res = context.getResources(); - final int index = DisplayUtils.getDisplayUniqueIdConfigIndex(res, displayUniqueId); - final TypedArray array = res.obtainTypedArray( - R.array.config_roundedCornerBottomDrawableArray); - Drawable drawable; - if (index >= 0 && index < array.length()) { - drawable = array.getDrawable(index); - } else { - drawable = context.getDrawable(R.drawable.rounded_corner_bottom); - } - array.recycle(); - return drawable; - } - private void updateRoundedCornerView(@BoundsPosition int pos, int id, @Nullable DisplayCutout cutout) { final View rounded = mOverlays[pos].getRootView().findViewById(id); @@ -1085,10 +966,9 @@ public class ScreenDecorations extends CoreStartable implements Tunable , Dumpab } } private boolean hasRoundedCorners() { - return mRoundedDefault.x > 0 - || mRoundedDefaultBottom.x > 0 - || mRoundedDefaultTop.x > 0 - || mIsRoundedCornerMultipleRadius; + return mRoundedCornerResDelegate.getBottomRoundedSize().getWidth() > 0 + || mRoundedCornerResDelegate.getTopRoundedSize().getWidth() > 0 + || mRoundedCornerResDelegate.isMultipleRadius(); } private boolean isDefaultShownOverlayPos(@BoundsPosition int pos, @@ -1154,33 +1034,28 @@ public class ScreenDecorations extends CoreStartable implements Tunable , Dumpab mExecutor.execute(() -> { if (mOverlays == null) return; if (SIZE.equals(key)) { - Point size = mRoundedDefault; - Point sizeTop = mRoundedDefaultTop; - Point sizeBottom = mRoundedDefaultBottom; if (newValue != null) { try { - int s = (int) (Integer.parseInt(newValue) * mDensity); - size = new Point(s, s); + mRoundedCornerResDelegate.updateTuningSizeFactor( + Integer.parseInt(newValue)); } catch (Exception e) { } } - updateRoundedCornerSize(size, sizeTop, sizeBottom); + updateRoundedCornerSize( + mRoundedCornerResDelegate.getTopRoundedSize(), + mRoundedCornerResDelegate.getBottomRoundedSize()); } }); } private void updateRoundedCornerDrawable() { - mRoundedCornerDrawable = getRoundedCornerDrawable(mContext, mDisplayUniqueId); - mRoundedCornerDrawableTop = getRoundedCornerTopDrawable(mContext, mDisplayUniqueId); - mRoundedCornerDrawableBottom = getRoundedCornerBottomDrawable(mContext, mDisplayUniqueId); + mRoundedCornerResDelegate.reloadAll(mDisplayUniqueId); updateRoundedCornerImageView(); } private void updateRoundedCornerImageView() { - final Drawable top = mRoundedCornerDrawableTop != null - ? mRoundedCornerDrawableTop : mRoundedCornerDrawable; - final Drawable bottom = mRoundedCornerDrawableBottom != null - ? mRoundedCornerDrawableBottom : mRoundedCornerDrawable; + final Drawable top = mRoundedCornerResDelegate.getTopRoundedDrawable(); + final Drawable bottom = mRoundedCornerResDelegate.getBottomRoundedDrawable(); if (mScreenDecorHwcLayer != null) { mScreenDecorHwcLayer.updateRoundedCornerDrawable(top, bottom); @@ -1205,6 +1080,20 @@ public class ScreenDecorations extends CoreStartable implements Tunable , Dumpab } } + private void updateHwLayerRoundedCornerDrawable() { + if (mScreenDecorHwcLayer == null) { + return; + } + + final Drawable topDrawable = mRoundedCornerResDelegate.getTopRoundedDrawable(); + final Drawable bottomDrawable = mRoundedCornerResDelegate.getBottomRoundedDrawable(); + + if (topDrawable == null || bottomDrawable == null) { + return; + } + mScreenDecorHwcLayer.updateRoundedCornerDrawable(topDrawable, bottomDrawable); + } + @VisibleForTesting boolean isTopRoundedCorner(@BoundsPosition int pos, int id) { switch (pos) { @@ -1224,19 +1113,21 @@ public class ScreenDecorations extends CoreStartable implements Tunable , Dumpab } } - private void updateRoundedCornerSize( - Point sizeDefault, - Point sizeTop, - Point sizeBottom) { - if (sizeTop.x == 0) { - sizeTop = sizeDefault; - } - if (sizeBottom.x == 0) { - sizeBottom = sizeDefault; + private void updateHwLayerRoundedCornerSize() { + if (mScreenDecorHwcLayer == null) { + return; } + final int topWidth = mRoundedCornerResDelegate.getTopRoundedSize().getWidth(); + final int bottomWidth = mRoundedCornerResDelegate.getBottomRoundedSize().getWidth(); + + mScreenDecorHwcLayer.updateRoundedCornerSize(topWidth, bottomWidth); + } + + private void updateRoundedCornerSize(Size sizeTop, Size sizeBottom) { + if (mScreenDecorHwcLayer != null) { - mScreenDecorHwcLayer.updateRoundedCornerSize(sizeTop.x, sizeBottom.x); + mScreenDecorHwcLayer.updateRoundedCornerSize(sizeTop.getWidth(), sizeBottom.getWidth()); return; } @@ -1256,10 +1147,10 @@ public class ScreenDecorations extends CoreStartable implements Tunable , Dumpab } @VisibleForTesting - protected void setSize(View view, Point pixelSize) { + protected void setSize(View view, Size pixelSize) { LayoutParams params = view.getLayoutParams(); - params.width = pixelSize.x; - params.height = pixelSize.y; + params.width = pixelSize.getWidth(); + params.height = pixelSize.getHeight(); view.setLayoutParams(params); } diff --git a/packages/SystemUI/src/com/android/systemui/accessibility/WindowMagnificationController.java b/packages/SystemUI/src/com/android/systemui/accessibility/WindowMagnificationController.java index 7e1a02626dc9..807ff21bf47a 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 @@ class WindowMagnificationController implements View.OnTouchListener, SurfaceHold 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 @@ class WindowMagnificationController implements View.OnTouchListener, SurfaceHold mMirrorWindowControl.destroyControl(); } mMirrorViewBounds.setEmpty(); + mSourceBounds.setEmpty(); updateSystemUIStateIfNeeded(); mContext.unregisterComponentCallbacks(this); } @@ -728,8 +729,12 @@ class WindowMagnificationController implements View.OnTouchListener, SurfaceHold /** * 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 @@ class WindowMagnificationController implements View.OnTouchListener, SurfaceHold mSourceBounds.offsetTo(mSourceBounds.left, mWindowBounds.height() - mSourceBounds.height()); } + return !mSourceBounds.equals(oldSourceBounds); } private void calculateMagnificationFrameBoundary() { @@ -1079,7 +1085,7 @@ class WindowMagnificationController implements View.OnTouchListener, SurfaceHold 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 64c2d2e3858e..c100a0744b85 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 @@ public class AuthController extends CoreStartable implements CommandQueue.Callba 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 57ca0f4826e9..2f2ca5b51fbf 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 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 @@ public abstract class AuthCredentialView extends LinearLayout { private String getLastAttemptBeforeWipeProfileMessage( @Utils.CredentialType int credentialType) { - return mDevicePolicyManager.getString( + return mDevicePolicyManager.getResources().getString( getLastAttemptBeforeWipeProfileUpdatableStringId(credentialType), () -> getLastAttemptBeforeWipeProfileDefaultMessage(credentialType)); } @@ -495,7 +495,7 @@ public abstract class AuthCredentialView extends LinearLayout { } 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 a27b9cd357f4..b811c51c952b 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 @@ class AuthRippleController @Inject constructor( } 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 bc7a3f6f4b13..975e0c5b32cd 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.LayoutInflater; 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 @@ import kotlin.Unit; * 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 UdfpsController implements DozeReceiver { 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 @@ public class UdfpsController implements DozeReceiver { 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 @@ public class UdfpsController implements DozeReceiver { 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 @@ public class UdfpsController implements DozeReceiver { && 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 @@ public class UdfpsController implements DozeReceiver { // 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 @@ public class UdfpsController implements DozeReceiver { } } else { Log.v(TAG, "onTouch | finger outside"); - onFingerUp(udfpsView); + onFingerUp(requestId, udfpsView); } } Trace.endSection(); @@ -482,7 +494,7 @@ public class UdfpsController implements DozeReceiver { } Log.v(TAG, "onTouch | finger up"); mAttemptedToDismissKeyguard = false; - onFingerUp(udfpsView); + onFingerUp(requestId, udfpsView); mFalsingManager.isFalseTouch(UDFPS_AUTHENTICATION); Trace.endSection(); break; @@ -679,7 +691,7 @@ public class UdfpsController implements DozeReceiver { // 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 @@ public class UdfpsController implements DozeReceiver { 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 @@ public class UdfpsController implements DozeReceiver { 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 @@ public class UdfpsController implements DozeReceiver { */ void onCancelUdfps() { if (mOverlay != null && mOverlay.getOverlayView() != null) { - onFingerUp(mOverlay.getOverlayView()); + onFingerUp(mOverlay.getRequestId(), mOverlay.getOverlayView()); } if (!mIsAodInterruptActive) { return; @@ -771,12 +785,17 @@ public class UdfpsController implements DozeReceiver { 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 @@ public class UdfpsController implements DozeReceiver { } } 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 @@ public class UdfpsController implements DozeReceiver { } } - 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 086894d2e670..ee43e932b344 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 @@ class UdfpsControllerOverlay( 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 @@ class UdfpsControllerOverlay( } } + /** 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 f78929f75b04..a9f340854689 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.power.PowerUI 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 @@ abstract class SystemUICoreStartableModule { @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/decor/RoundedCornerResDelegate.kt b/packages/SystemUI/src/com/android/systemui/decor/RoundedCornerResDelegate.kt new file mode 100644 index 000000000000..c817f89c7a9b --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/decor/RoundedCornerResDelegate.kt @@ -0,0 +1,201 @@ +/* + * Copyright (C) 2022 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.systemui.decor + +import android.annotation.ArrayRes +import android.annotation.DrawableRes +import android.content.res.Resources +import android.graphics.drawable.Drawable +import android.util.DisplayUtils +import android.util.Size +import android.view.RoundedCorners +import com.android.systemui.Dumpable +import com.android.systemui.R +import java.io.FileDescriptor +import java.io.PrintWriter + +class RoundedCornerResDelegate( + private val res: Resources, + private var displayUniqueId: String? +) : Dumpable { + + private val density: Float + get() = res.displayMetrics.density + + var isMultipleRadius: Boolean = false + private set + + private var roundedDrawable: Drawable? = null + + var topRoundedDrawable: Drawable? = null + private set + + var bottomRoundedDrawable: Drawable? = null + private set + + private var roundedSize = Size(0, 0) + + var topRoundedSize = Size(0, 0) + private set + + var bottomRoundedSize = Size(0, 0) + private set + + init { + reloadDrawables() + reloadMeasures() + } + + fun reloadAll(newDisplayUniqueId: String?) { + displayUniqueId = newDisplayUniqueId + reloadDrawables() + reloadMeasures() + } + + private fun reloadDrawables() { + val configIdx = DisplayUtils.getDisplayUniqueIdConfigIndex(res, displayUniqueId) + isMultipleRadius = getIsMultipleRadius(configIdx) + + roundedDrawable = getDrawable( + displayConfigIndex = configIdx, + arrayResId = R.array.config_roundedCornerDrawableArray, + backupDrawableId = R.drawable.rounded + ) + topRoundedDrawable = getDrawable( + displayConfigIndex = configIdx, + arrayResId = R.array.config_roundedCornerTopDrawableArray, + backupDrawableId = R.drawable.rounded_corner_top + ) ?: roundedDrawable + bottomRoundedDrawable = getDrawable( + displayConfigIndex = configIdx, + arrayResId = R.array.config_roundedCornerBottomDrawableArray, + backupDrawableId = R.drawable.rounded_corner_bottom + ) ?: roundedDrawable + + // If config_roundedCornerMultipleRadius set as true, ScreenDecorations respect the + // (width, height) size of drawable/rounded.xml instead of rounded_corner_radius + if (isMultipleRadius) { + roundedSize = Size( + roundedDrawable?.intrinsicWidth ?: 0, + roundedDrawable?.intrinsicHeight ?: 0) + topRoundedDrawable?.let { + topRoundedSize = Size(it.intrinsicWidth, it.intrinsicHeight) + } + bottomRoundedDrawable?.let { + bottomRoundedSize = Size(it.intrinsicWidth, it.intrinsicHeight) + } + } else { + val defaultRadius = RoundedCorners.getRoundedCornerRadius(res, displayUniqueId) + val topRadius = RoundedCorners.getRoundedCornerTopRadius(res, displayUniqueId) + val bottomRadius = RoundedCorners.getRoundedCornerBottomRadius(res, displayUniqueId) + roundedSize = Size(defaultRadius, defaultRadius) + topRoundedSize = Size(topRadius, topRadius) + bottomRoundedSize = Size(bottomRadius, bottomRadius) + } + + if (topRoundedSize.width == 0) { + topRoundedSize = roundedSize + } + if (bottomRoundedSize.width == 0) { + bottomRoundedSize = roundedSize + } + } + + private fun reloadMeasures(roundedSizeFactor: Int? = null) { + // If config_roundedCornerMultipleRadius set as true, ScreenDecorations respect the + // (width, height) size of drawable/rounded.xml instead of rounded_corner_radius + if (isMultipleRadius) { + roundedSize = Size( + roundedDrawable?.intrinsicWidth ?: 0, + roundedDrawable?.intrinsicHeight ?: 0) + topRoundedDrawable?.let { + topRoundedSize = Size(it.intrinsicWidth, it.intrinsicHeight) + } + bottomRoundedDrawable?.let { + bottomRoundedSize = Size(it.intrinsicWidth, it.intrinsicHeight) + } + } else { + val defaultRadius = RoundedCorners.getRoundedCornerRadius(res, displayUniqueId) + val topRadius = RoundedCorners.getRoundedCornerTopRadius(res, displayUniqueId) + val bottomRadius = RoundedCorners.getRoundedCornerBottomRadius(res, displayUniqueId) + roundedSize = Size(defaultRadius, defaultRadius) + topRoundedSize = Size(topRadius, topRadius) + bottomRoundedSize = Size(bottomRadius, bottomRadius) + } + + roundedSizeFactor ?.let { + val length: Int = (it * density).toInt() + roundedSize = Size(length, length) + } + + if (topRoundedSize.width == 0) { + topRoundedSize = roundedSize + } + if (bottomRoundedSize.width == 0) { + bottomRoundedSize = roundedSize + } + } + + fun updateTuningSizeFactor(factor: Int) { + reloadMeasures(factor) + } + + /** + * Gets whether the rounded corners are multiple radii for current display. + * + * Loads the default config {@link R.bool#config_roundedCornerMultipleRadius} if + * {@link com.android.internal.R.array#config_displayUniqueIdArray} is not set. + */ + private fun getIsMultipleRadius(displayConfigIndex: Int): Boolean { + val isMultipleRadius: Boolean + res.obtainTypedArray(R.array.config_roundedCornerMultipleRadiusArray).let { array -> + isMultipleRadius = if (displayConfigIndex >= 0 && displayConfigIndex < array.length()) { + array.getBoolean(displayConfigIndex, false) + } else { + res.getBoolean(R.bool.config_roundedCornerMultipleRadius) + } + array.recycle() + } + return isMultipleRadius + } + + private fun getDrawable( + displayConfigIndex: Int, + @ArrayRes arrayResId: Int, + @DrawableRes backupDrawableId: Int + ): Drawable? { + val drawable: Drawable? + res.obtainTypedArray(arrayResId).let { array -> + drawable = if (displayConfigIndex >= 0 && displayConfigIndex < array.length()) { + array.getDrawable(displayConfigIndex) + } else { + res.getDrawable(backupDrawableId, null) + } + array.recycle() + } + return drawable + } + + override fun dump(fd: FileDescriptor, pw: PrintWriter, args: Array<out String>) { + pw.println("RoundedCornerResDelegate state:") + pw.println(" isMultipleRadius:$isMultipleRadius") + pw.println(" roundedSize(w,h)=(${roundedSize.width},${roundedSize.height})") + pw.println(" topRoundedSize(w,h)=(${topRoundedSize.width},${topRoundedSize.height})") + pw.println(" bottomRoundedSize(w,h)=(${bottomRoundedSize.width}," + + "${bottomRoundedSize.height})") + } +}
\ 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 b8b4092ccf2f..dfb27eff722b 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 @@ public class DozeScreenBrightness extends BroadcastReceiver implements DozeMachi 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 @@ public class DozeScreenBrightness extends BroadcastReceiver implements DozeMachi @Override public void transitionTo(DozeMachine.State oldState, DozeMachine.State newState) { + mState = newState; switch (newState) { case INITIALIZED: resetBrightnessToDefault(); @@ -262,8 +264,9 @@ public class DozeScreenBrightness extends BroadcastReceiver implements DozeMachi */ 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 d2ab61149d26..59a17bad5069 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 @@ public class DreamOverlayStatusBarView extends ConstraintLayout { 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 a25a7423770e..761f28c5ac3b 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 com.android.systemui.util.time.DateFormatUtil; import java.util.Locale; import java.util.Map; +import java.util.concurrent.Executor; import javax.inject.Inject; @@ -62,6 +64,9 @@ public class DreamOverlayStatusBarViewController extends ViewController<DreamOve 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 class DreamOverlayStatusBarViewController extends ViewController<DreamOve public DreamOverlayStatusBarViewController( DreamOverlayStatusBarView view, @Main Resources resources, + @Main Executor mainExecutor, ConnectivityManager connectivityManager, TouchInsetManager.TouchInsetSession touchInsetSession, AlarmManager alarmManager, @@ -141,6 +147,7 @@ public class DreamOverlayStatusBarViewController extends ViewController<DreamOve ZenModeController zenModeController) { super(view); mResources = resources; + mMainExecutor = mainExecutor; mConnectivityManager = connectivityManager; mTouchInsetSession = touchInsetSession; mAlarmManager = alarmManager; @@ -157,6 +164,8 @@ public class DreamOverlayStatusBarViewController extends ViewController<DreamOve @Override protected void onViewAttached() { + mIsAttached = true; + updateNotificationsStatusIcon(); mConnectivityManager.registerNetworkCallback(mNetworkRequest, mNetworkCallback); @@ -181,6 +190,8 @@ public class DreamOverlayStatusBarViewController extends ViewController<DreamOve mNextAlarmController.removeCallback(mNextAlarmCallback); mConnectivityManager.unregisterNetworkCallback(mNetworkCallback); mTouchInsetSession.clear(); + + mIsAttached = false; } private void updateWifiUnavailableStatusIcon() { @@ -189,14 +200,14 @@ public class DreamOverlayStatusBarViewController extends ViewController<DreamOve 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 @@ public class DreamOverlayStatusBarViewController extends ViewController<DreamOve .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 @@ public class DreamOverlayStatusBarViewController extends ViewController<DreamOve 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 @@ public class DreamOverlayStatusBarViewController extends ViewController<DreamOve } 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 6861c7479161..1ca06b25aa9f 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 @@ public class DreamClockDateComplication implements Complication { */ @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 @@ public class DreamClockDateComplication implements Complication { } /** - * 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 936767a60233..7f67ecd19175 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 @@ public class DreamClockTimeComplication implements Complication { */ @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 @@ public class DreamClockTimeComplication implements Complication { } /** - * 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 dd7f10c204e1..000000000000 --- 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 000000000000..eb2fc5d1a93e --- /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 de11b61f4759..000000000000 --- 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 000000000000..3ad7d3ded749 --- /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 8e4fb3783f4a..62a4140c6745 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 @@ import dagger.Module; * 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/FeatureFlagsDebug.java b/packages/SystemUI/src/com/android/systemui/flags/FeatureFlagsDebug.java index 0c5f7ebb6e16..3335c8d62f46 100644 --- a/packages/SystemUI/src/com/android/systemui/flags/FeatureFlagsDebug.java +++ b/packages/SystemUI/src/com/android/systemui/flags/FeatureFlagsDebug.java @@ -50,9 +50,9 @@ import java.util.Map; import java.util.Objects; import java.util.TreeMap; import java.util.function.Consumer; -import java.util.function.Supplier; import javax.inject.Inject; +import javax.inject.Named; /** * Concrete implementation of the a Flag manager that returns default values for debug builds @@ -66,12 +66,13 @@ import javax.inject.Inject; @SysUISingleton public class FeatureFlagsDebug implements FeatureFlags, Dumpable { private static final String TAG = "SysUIFlags"; + static final String ALL_FLAGS = "all_flags"; private final FlagManager mFlagManager; private final SecureSettings mSecureSettings; private final Resources mResources; private final SystemPropertiesHelper mSystemProperties; - private final Supplier<Map<Integer, Flag<?>>> mFlagsCollector; + private final Map<Integer, Flag<?>> mAllFlags; private final Map<Integer, Boolean> mBooleanFlagCache = new TreeMap<>(); private final Map<Integer, String> mStringFlagCache = new TreeMap<>(); private final IStatusBarService mBarService; @@ -84,13 +85,13 @@ public class FeatureFlagsDebug implements FeatureFlags, Dumpable { SystemPropertiesHelper systemProperties, @Main Resources resources, DumpManager dumpManager, - @Nullable Supplier<Map<Integer, Flag<?>>> flagsCollector, + @Named(ALL_FLAGS) Map<Integer, Flag<?>> allFlags, IStatusBarService barService) { mFlagManager = flagManager; mSecureSettings = secureSettings; mResources = resources; mSystemProperties = systemProperties; - mFlagsCollector = flagsCollector != null ? flagsCollector : Flags::collectFlags; + mAllFlags = allFlags; IntentFilter filter = new IntentFilter(); filter.addAction(ACTION_SET_FLAG); filter.addAction(ACTION_GET_FLAGS); @@ -107,7 +108,7 @@ public class FeatureFlagsDebug implements FeatureFlags, Dumpable { int id = flag.getId(); if (!mBooleanFlagCache.containsKey(id)) { mBooleanFlagCache.put(id, - readFlagValue(id, flag.getDefault(), BooleanFlagSerializer.INSTANCE)); + readFlagValue(id, flag.getDefault())); } return mBooleanFlagCache.get(id); @@ -118,8 +119,7 @@ public class FeatureFlagsDebug implements FeatureFlags, Dumpable { int id = flag.getId(); if (!mBooleanFlagCache.containsKey(id)) { mBooleanFlagCache.put(id, - readFlagValue(id, mResources.getBoolean(flag.getResourceId()), - BooleanFlagSerializer.INSTANCE)); + readFlagValue(id, mResources.getBoolean(flag.getResourceId()))); } return mBooleanFlagCache.get(id); @@ -129,8 +129,13 @@ public class FeatureFlagsDebug implements FeatureFlags, Dumpable { public boolean isEnabled(@NonNull SysPropBooleanFlag flag) { int id = flag.getId(); if (!mBooleanFlagCache.containsKey(id)) { + // Use #readFlagValue to get the default. That will allow it to fall through to + // teamfood if need be. mBooleanFlagCache.put( - id, mSystemProperties.getBoolean(flag.getName(), flag.getDefault())); + id, + mSystemProperties.getBoolean( + flag.getName(), + readFlagValue(id, flag.getDefault()))); } return mBooleanFlagCache.get(id); @@ -161,6 +166,19 @@ public class FeatureFlagsDebug implements FeatureFlags, Dumpable { return mStringFlagCache.get(id); } + /** Specific override for Boolean flags that checks against the teamfood list.*/ + private boolean readFlagValue(int id, boolean defaultValue) { + Boolean result = readFlagValueInternal(id, BooleanFlagSerializer.INSTANCE); + // Only check for teamfood if the default is false. + if (!defaultValue && result == null && id != Flags.TEAMFOOD.getId()) { + if (mAllFlags.containsKey(id) && mAllFlags.get(id).getTeamfood()) { + return isEnabled(Flags.TEAMFOOD); + } + } + + return result == null ? defaultValue : result; + } + @NonNull private <T> T readFlagValue(int id, @NonNull T defaultValue, FlagSerializer<T> serializer) { requireNonNull(defaultValue, "defaultValue"); @@ -266,8 +284,7 @@ public class FeatureFlagsDebug implements FeatureFlags, Dumpable { if (ACTION_SET_FLAG.equals(action)) { handleSetFlag(intent.getExtras()); } else if (ACTION_GET_FLAGS.equals(action)) { - Map<Integer, Flag<?>> knownFlagMap = mFlagsCollector.get(); - ArrayList<Flag<?>> flags = new ArrayList<>(knownFlagMap.values()); + ArrayList<Flag<?>> flags = new ArrayList<>(mAllFlags.values()); // Convert all flags to parcelable flags. ArrayList<ParcelableFlag<?>> pFlags = new ArrayList<>(); @@ -296,12 +313,11 @@ public class FeatureFlagsDebug implements FeatureFlags, Dumpable { return; } - Map<Integer, Flag<?>> flagMap = mFlagsCollector.get(); - if (!flagMap.containsKey(id)) { + if (!mAllFlags.containsKey(id)) { Log.w(TAG, "Tried to set unknown id: " + id); return; } - Flag<?> flag = flagMap.get(id); + Flag<?> flag = mAllFlags.get(id); if (!extras.containsKey(EXTRA_VALUE)) { eraseFlag(flag); @@ -338,13 +354,16 @@ public class FeatureFlagsDebug implements FeatureFlags, Dumpable { @Nullable private ParcelableFlag<?> toParcelableFlag(Flag<?> f) { if (f instanceof BooleanFlag) { - return new BooleanFlag(f.getId(), isEnabled((BooleanFlag) f)); + return new BooleanFlag(f.getId(), isEnabled((BooleanFlag) f), f.getTeamfood()); } if (f instanceof ResourceBooleanFlag) { - return new BooleanFlag(f.getId(), isEnabled((ResourceBooleanFlag) f)); + return new BooleanFlag( + f.getId(), isEnabled((ResourceBooleanFlag) f), f.getTeamfood()); } if (f instanceof SysPropBooleanFlag) { - return new BooleanFlag(f.getId(), isEnabled((SysPropBooleanFlag) f)); + // TODO(b/223379190): Teamfood not supported for sysprop flags yet. + return new BooleanFlag( + f.getId(), isEnabled((SysPropBooleanFlag) f), false); } // TODO: add support for other flag types. diff --git a/packages/SystemUI/src/com/android/systemui/flags/Flags.java b/packages/SystemUI/src/com/android/systemui/flags/Flags.java index 2db3de173257..61cfe925f640 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 @@ public class Flags { /***************************************/ // 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 c01d2c316a93..bf464ecdec98 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.provider.Settings.System.SCREEN_OFF_TIMEOUT; 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.NotificationShadeDepthController; 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 class KeyguardViewMediator extends CoreStartable implements Dumpable, 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 @@ public class KeyguardViewMediator extends CoreStartable implements Dumpable, 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 @@ public class KeyguardViewMediator extends CoreStartable implements Dumpable, // 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 @@ public class KeyguardViewMediator extends CoreStartable implements Dumpable, 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 b3371831454b..e6b650b20711 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 @@ public class WorkLockActivity extends Activity { // 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 c69f947f5f3f..71dfa7433c32 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.DismissCallbackRegistry; 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 @@ public class KeyguardModule { 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 510d15bd7b73..ffdd5376b12e 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 @@ public class MediaControlPanel { 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 @@ public class MediaControlPanel { 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 @@ public class MediaControlPanel { mMediaOutputDialogFactory = mediaOutputDialogFactory; mMediaCarouselController = mediaCarouselController; mFalsingManager = falsingManager; - mMediaFlags = mediaFlags; mSystemClock = systemClock; loadDimens(); @@ -506,9 +504,8 @@ public class MediaControlPanel { 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 9e14fe91f21d..56d8c6486631 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 @@ class MediaDataManager( 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 @@ class MediaDataManager( } } - // 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 dd35a9a81399..59237d936d72 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 @@ class MediaFlags @Inject constructor(private val featureFlags: FeatureFlags) { /** * 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 7a4dee294dd6..d472aeee1073 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 @@ class MediaHierarchyManager @Inject constructor( @TransformationType fun calculateTransformationType(): Int { if (isTransitioningToFullShade) { - if (inSplitShade) { + if (inSplitShade && areGuidedTransitionHostsVisible()) { return TRANSFORMATION_TYPE_TRANSITION } return TRANSFORMATION_TYPE_FADE @@ -829,6 +829,11 @@ class MediaHierarchyManager @Inject constructor( 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/MediaHost.kt b/packages/SystemUI/src/com/android/systemui/media/MediaHost.kt index 0a4b68b501f7..eb209f723cb5 100644 --- a/packages/SystemUI/src/com/android/systemui/media/MediaHost.kt +++ b/packages/SystemUI/src/com/android/systemui/media/MediaHost.kt @@ -192,6 +192,14 @@ class MediaHost constructor( } } + override var squishFraction: Float = 1.0f + set(value) { + if (!value.equals(field)) { + field = value + changedListener?.invoke() + } + } + override var showsOnlyActiveMedia: Boolean = false set(value) { if (!value.equals(field)) { @@ -242,6 +250,7 @@ class MediaHost constructor( override fun copy(): MediaHostState { val mediaHostState = MediaHostStateHolder() mediaHostState.expansion = expansion + mediaHostState.squishFraction = squishFraction mediaHostState.showsOnlyActiveMedia = showsOnlyActiveMedia mediaHostState.measurementInput = measurementInput?.copy() mediaHostState.visible = visible @@ -260,6 +269,9 @@ class MediaHost constructor( if (expansion != other.expansion) { return false } + if (squishFraction != other.squishFraction) { + return false + } if (showsOnlyActiveMedia != other.showsOnlyActiveMedia) { return false } @@ -278,6 +290,7 @@ class MediaHost constructor( override fun hashCode(): Int { var result = measurementInput?.hashCode() ?: 0 result = 31 * result + expansion.hashCode() + result = 31 * result + squishFraction.hashCode() result = 31 * result + falsingProtectionNeeded.hashCode() result = 31 * result + showsOnlyActiveMedia.hashCode() result = 31 * result + if (visible) 1 else 2 @@ -318,6 +331,11 @@ interface MediaHostState { var expansion: Float /** + * Fraction of the height animation. + */ + var squishFraction: Float + + /** * Is this host only showing active media or is it showing all of them including resumption? */ var showsOnlyActiveMedia: Boolean diff --git a/packages/SystemUI/src/com/android/systemui/media/MediaViewController.kt b/packages/SystemUI/src/com/android/systemui/media/MediaViewController.kt index 591aad1014bd..a60016b23a7c 100644 --- a/packages/SystemUI/src/com/android/systemui/media/MediaViewController.kt +++ b/packages/SystemUI/src/com/android/systemui/media/MediaViewController.kt @@ -18,13 +18,11 @@ package com.android.systemui.media import android.content.Context import android.content.res.Configuration +import androidx.annotation.VisibleForTesting import androidx.constraintlayout.widget.ConstraintSet import com.android.systemui.R import com.android.systemui.statusbar.policy.ConfigurationController -import com.android.systemui.util.animation.MeasurementOutput -import com.android.systemui.util.animation.TransitionLayout -import com.android.systemui.util.animation.TransitionLayoutController -import com.android.systemui.util.animation.TransitionViewState +import com.android.systemui.util.animation.* import javax.inject.Inject /** @@ -270,7 +268,6 @@ class MediaViewController @Inject constructor( TYPE.PLAYER_SESSION -> PlayerSessionViewHolder.gutsIds TYPE.RECOMMENDATION -> RecommendationViewHolder.gutsIds } - controlsIds.forEach { id -> viewState.widgetStates.get(id)?.let { state -> // Make sure to use the unmodified state if guts are not visible. @@ -282,59 +279,79 @@ class MediaViewController @Inject constructor( viewState.widgetStates.get(id)?.alpha = if (isGutsVisible) 1f else 0f viewState.widgetStates.get(id)?.gone = !isGutsVisible } - if (shouldHideGutsSettings) { viewState.widgetStates.get(R.id.settings)?.gone = true } } /** + * Apply squishFraction to a copy of viewState such that the cached version is untouched. + */ + private fun squishViewState(viewState: TransitionViewState, + squishFraction: Float): TransitionViewState { + val squishedViewState = viewState.copy() + squishedViewState.height = (squishedViewState.height * squishFraction).toInt() + val albumArtViewState = viewState.widgetStates.get(R.id.album_art) + if (albumArtViewState != null) { + albumArtViewState.height = squishedViewState.height + } + return squishedViewState; + } + + /** * Obtain a new viewState for a given media state. This usually returns a cached state, but if * it's not available, it will recreate one by measuring, which may be expensive. */ - private fun obtainViewState(state: MediaHostState?): TransitionViewState? { + @VisibleForTesting + public fun obtainViewState(state: MediaHostState?): TransitionViewState? { if (state == null || state.measurementInput == null) { return null } // Only a subset of the state is relevant to get a valid viewState. Let's get the cachekey var cacheKey = getKey(state, isGutsVisible, tmpKey) val viewState = viewStates[cacheKey] + if (viewState != null) { // we already have cached this measurement, let's continue + if (state.squishFraction < 1f) { + return squishViewState(viewState, state.squishFraction); + } return viewState } // Copy the key since this might call recursively into it and we're using tmpKey cacheKey = cacheKey.copy() val result: TransitionViewState? - if (transitionLayout != null) { - // Let's create a new measurement - if (state.expansion == 0.0f || state.expansion == 1.0f) { - result = transitionLayout!!.calculateViewState( - state.measurementInput!!, - constraintSetForExpansion(state.expansion), - TransitionViewState()) - - setGutsViewState(result) - // We don't want to cache interpolated or null states as this could quickly fill up - // our cache. We only cache the start and the end states since the interpolation - // is cheap - viewStates[cacheKey] = result - } else { - // This is an interpolated state - val startState = state.copy().also { it.expansion = 0.0f } - - // Given that we have a measurement and a view, let's get (guaranteed) viewstates - // from the start and end state and interpolate them - val startViewState = obtainViewState(startState) as TransitionViewState - val endState = state.copy().also { it.expansion = 1.0f } - val endViewState = obtainViewState(endState) as TransitionViewState - result = layoutController.getInterpolatedState( - startViewState, - endViewState, - state.expansion) - } + if (transitionLayout == null) { + return null + } + // Not cached. Let's create a new measurement + if (state.expansion == 0.0f || state.expansion == 1.0f) { + result = transitionLayout!!.calculateViewState( + state.measurementInput!!, + constraintSetForExpansion(state.expansion), + TransitionViewState()) + // We don't want to cache interpolated or null states as this could quickly fill up + // our cache. We only cache the start and the end states since the interpolation + // is cheap + setGutsViewState(result) + viewStates[cacheKey] = result } else { - result = null + // This is an interpolated state + val startState = state.copy().also { it.expansion = 0.0f } + + // Given that we have a measurement and a view, let's get (guaranteed) viewstates + // from the start and end state and interpolate them + val startViewState = obtainViewState(startState) as TransitionViewState + val endState = state.copy().also { it.expansion = 1.0f } + + val endViewState = obtainViewState(endState) as TransitionViewState + result = layoutController.getInterpolatedState( + startViewState, + endViewState, + state.expansion) + } + if (state.squishFraction < 1f) { + return squishViewState(result, state.squishFraction); } return result } 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 0b23ad50a726..a6464829623f 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 @@ public class MediaOutputAdapter extends MediaOutputBaseAdapter { 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 @@ public class MediaOutputAdapter extends MediaOutputBaseAdapter { && !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 @@ public class MediaOutputAdapter extends MediaOutputBaseAdapter { 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 @@ public class MediaOutputAdapter extends MediaOutputBaseAdapter { 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 @@ public class MediaOutputAdapter extends MediaOutputBaseAdapter { 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 @@ public class MediaOutputAdapter extends MediaOutputBaseAdapter { 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 @@ public class MediaOutputAdapter extends MediaOutputBaseAdapter { @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 62d5c8e51005..df0c14b25c26 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 @@ public abstract class MediaOutputBaseAdapter extends 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 @@ public abstract class MediaOutputBaseAdapter extends .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 a8141c0e2fec..dcb1c7c4637c 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 @@ public abstract class MediaOutputBaseDialog extends SystemUIDialog implements 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 0b6c68d17a4c..ea7f7f2bb646 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 @@ public class MediaOutputController implements LocalMediaManager.DeviceCallback, 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 @@ public class MediaOutputController implements LocalMediaManager.DeviceCallback, 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 @@ public class MediaOutputController implements LocalMediaManager.DeviceCallback, } 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 @@ public class MediaOutputController implements LocalMediaManager.DeviceCallback, 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 getColorPositiveButtonText() { + return mColorPositiveButtonText; } - public int getColorInactiveItem() { - return mColorInactiveItem; + 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 3961f079748b..e4b8874ff601 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 @@ class MediaTttCommandLineHelper @Inject constructor( 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 71cacac7f4df..54b0c1345601 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.MotionEvent 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 class MediaTttChipControllerCommon<T : ChipInfoCommon>( 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 @@ abstract class MediaTttChipControllerCommon<T : ChipInfoCommon>( 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 - } - /** 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 - } + appIconView.contentDescription = appNameOverride ?: iconInfo.iconName + appIconView.setImageDrawable(appIconDrawableOverride ?: iconInfo.icon) } - /** 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 + /** + * 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) + } } + 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 @@ object MediaTttRemovalReason { 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 44965d705802..072263fcf38c 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 @@ class MediaTttChipControllerReceiver @Inject constructor( 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/NavigationBar.java b/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBar.java index ec6094dd9973..d8d86779ea0a 100644 --- a/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBar.java +++ b/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBar.java @@ -47,6 +47,7 @@ import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_A import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_IME_SHOWING; import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_IME_SWITCHER_SHOWING; import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_NAV_BAR_HIDDEN; +import static com.android.systemui.shared.system.QuickStepContract.isGesturalMode; import static com.android.systemui.statusbar.phone.BarTransitions.MODE_LIGHTS_OUT; import static com.android.systemui.statusbar.phone.BarTransitions.MODE_LIGHTS_OUT_TRANSPARENT; import static com.android.systemui.statusbar.phone.BarTransitions.MODE_OPAQUE; @@ -61,7 +62,6 @@ import android.app.ActivityTaskManager; import android.app.IActivityTaskManager; import android.app.StatusBarManager; import android.content.BroadcastReceiver; -import android.content.ContentResolver; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; @@ -107,13 +107,15 @@ import com.android.internal.logging.UiEventLogger; import com.android.internal.logging.nano.MetricsProto.MetricsEvent; import com.android.internal.util.LatencyTracker; import com.android.internal.view.AppearanceRegion; +import com.android.systemui.Gefingerpoken; import com.android.systemui.R; -import com.android.systemui.accessibility.AccessibilityButtonModeObserver; import com.android.systemui.assist.AssistManager; import com.android.systemui.broadcast.BroadcastDispatcher; import com.android.systemui.dagger.qualifiers.Main; import com.android.systemui.model.SysUiState; +import com.android.systemui.navigationbar.NavigationModeController.ModeChangedListener; import com.android.systemui.navigationbar.buttons.ButtonDispatcher; +import com.android.systemui.navigationbar.buttons.DeadZone; import com.android.systemui.navigationbar.buttons.KeyButtonView; import com.android.systemui.navigationbar.buttons.RotationContextButton; import com.android.systemui.navigationbar.gestural.QuickswitchOrientedNavHandle; @@ -125,6 +127,7 @@ import com.android.systemui.shared.rotation.RotationButton; import com.android.systemui.shared.rotation.RotationButtonController; import com.android.systemui.shared.system.ActivityManagerWrapper; import com.android.systemui.shared.system.QuickStepContract; +import com.android.systemui.shared.system.SysUiStatsLog; import com.android.systemui.statusbar.AutoHideUiElement; import com.android.systemui.statusbar.CommandQueue; import com.android.systemui.statusbar.CommandQueue.Callbacks; @@ -146,15 +149,15 @@ import java.util.Locale; import java.util.Optional; import java.util.function.Consumer; -import javax.inject.Inject; - import dagger.Lazy; +import dagger.assisted.Assisted; +import dagger.assisted.AssistedFactory; +import dagger.assisted.AssistedInject; /** * Contains logic for a navigation bar view. */ -public class NavigationBar implements View.OnAttachStateChangeListener, - Callbacks, NavigationModeController.ModeChangedListener { +public class NavigationBar implements View.OnAttachStateChangeListener, Callbacks { public static final String TAG = "NavigationBar"; private static final boolean DEBUG = false; @@ -181,7 +184,6 @@ public class NavigationBar implements View.OnAttachStateChangeListener, private final NotificationRemoteInputManager mNotificationRemoteInputManager; private final OverviewProxyService mOverviewProxyService; private final NavigationModeController mNavigationModeController; - private final AccessibilityButtonModeObserver mAccessibilityButtonModeObserver; private final BroadcastDispatcher mBroadcastDispatcher; private final CommandQueue mCommandQueue; private final Optional<Pip> mPipOptional; @@ -200,8 +202,7 @@ public class NavigationBar implements View.OnAttachStateChangeListener, private @WindowVisibleState int mNavigationBarWindowState = WINDOW_STATE_SHOWING; private int mNavigationIconHints = 0; - private @TransitionMode int mNavigationBarMode; - private ContentResolver mContentResolver; + private @TransitionMode int mTransitionMode; private boolean mLongPressHomeEnabled; private int mDisabledFlags1; @@ -255,7 +256,8 @@ public class NavigationBar implements View.OnAttachStateChangeListener, private int mCurrentRotation; private ViewTreeObserver.OnGlobalLayoutListener mOrientationHandleGlobalLayoutListener; private boolean mShowOrientedHandleForImmersiveMode; - + private DeadZone mDeadZone; + private boolean mImeVisible; @com.android.internal.annotations.VisibleForTesting public enum NavBarActionEvent implements UiEventLogger.UiEventEnum { @@ -471,15 +473,16 @@ public class NavigationBar implements View.OnAttachStateChangeListener, } }; - private NavigationBar(Context context, - WindowManager windowManager, + @AssistedInject + NavigationBar( + @Assisted Context context, + @Assisted WindowManager windowManager, Lazy<AssistManager> assistManagerLazy, AccessibilityManager accessibilityManager, DeviceProvisionedController deviceProvisionedController, MetricsLogger metricsLogger, OverviewProxyService overviewProxyService, NavigationModeController navigationModeController, - AccessibilityButtonModeObserver accessibilityButtonModeObserver, StatusBarStateController statusBarStateController, SysUiState sysUiFlagsContainer, BroadcastDispatcher broadcastDispatcher, @@ -514,7 +517,6 @@ public class NavigationBar implements View.OnAttachStateChangeListener, mNotificationRemoteInputManager = notificationRemoteInputManager; mOverviewProxyService = overviewProxyService; mNavigationModeController = navigationModeController; - mAccessibilityButtonModeObserver = accessibilityButtonModeObserver; mBroadcastDispatcher = broadcastDispatcher; mCommandQueue = commandQueue; mPipOptional = pipOptional; @@ -532,7 +534,7 @@ public class NavigationBar implements View.OnAttachStateChangeListener, mTelecomManagerOptional = telecomManagerOptional; mInputMethodManager = inputMethodManager; - mNavBarMode = mNavigationModeController.addListener(this); + mNavBarMode = mNavigationModeController.addListener(mModeChangedListener); } public NavigationBarView getView() { @@ -546,6 +548,11 @@ public class NavigationBar implements View.OnAttachStateChangeListener, R.layout.navigation_bar, mFrame); barView.addOnAttachStateChangeListener(this); mNavigationBarView = barView.findViewById(R.id.navigation_bar_view); + mDeadZone = new DeadZone(mNavigationBarView); + mNavigationBarView.setTouchHandler(mTouchHandler); + mNavigationBarView.setNavBarMode(mNavBarMode); + + mNavigationBarView.updateRotationButton(); mNavigationBarView.setVisibility(initialVisibility ? View.VISIBLE : View.INVISIBLE); @@ -558,7 +565,6 @@ public class NavigationBar implements View.OnAttachStateChangeListener, mCommandQueue.addCallback(this); mLongPressHomeEnabled = mNavBarHelper.getLongPressHomeEnabled(); - mContentResolver = mContext.getContentResolver(); mNavBarHelper.init(); mAllowForceNavBarHandleOpaque = mContext.getResources().getBoolean( R.bool.allow_force_nav_bar_handle_opaque); @@ -597,7 +603,7 @@ public class NavigationBar implements View.OnAttachStateChangeListener, setAutoHideController(/* autoHideController */ null); mCommandQueue.removeCallback(this); mWindowManager.removeViewImmediate(mNavigationBarView.getRootView()); - mNavigationModeController.removeListener(this); + mNavigationModeController.removeListener(mModeChangedListener); mNavBarHelper.removeNavTaskStateUpdater(mNavbarTaskbarStateUpdater); mNavBarHelper.destroy(); @@ -612,15 +618,16 @@ public class NavigationBar implements View.OnAttachStateChangeListener, final Display display = v.getDisplay(); mNavigationBarView.setComponents(mRecentsOptional); mNavigationBarView.setComponents(mCentralSurfacesOptionalLazy.get().get().getPanelController()); - mNavigationBarView.setDisabledFlags(mDisabledFlags1); + mNavigationBarView.setDisabledFlags(mDisabledFlags1, mSysUiFlagsContainer); mNavigationBarView.setOnVerticalChangedListener(this::onVerticalChanged); mNavigationBarView.setOnTouchListener(this::onNavigationTouch); if (mSavedState != null) { mNavigationBarView.getLightTransitionsController().restoreState(mSavedState); } - mNavigationBarView.setNavigationIconHints(mNavigationIconHints); + setNavigationIconHints(mNavigationIconHints); mNavigationBarView.setWindowVisible(isNavBarWindowVisible()); mNavigationBarView.setBehavior(mBehavior); + mNavigationBarView.setNavBarMode(mNavBarMode); mNavBarHelper.registerNavTaskStateUpdater(mNavbarTaskbarStateUpdater); @@ -865,8 +872,8 @@ public class NavigationBar implements View.OnAttachStateChangeListener, pw.println(" mLongPressHomeEnabled=" + mLongPressHomeEnabled); pw.println(" mNavigationBarWindowState=" + windowStateToString(mNavigationBarWindowState)); - pw.println(" mNavigationBarMode=" - + BarTransitions.modeToString(mNavigationBarMode)); + pw.println(" mTransitionMode=" + + BarTransitions.modeToString(mTransitionMode)); pw.println(" mTransientShown=" + mTransientShown); pw.println(" mTransientShownFromGestureOnSystemBar=" + mTransientShownFromGestureOnSystemBar); @@ -888,11 +895,7 @@ public class NavigationBar implements View.OnAttachStateChangeListener, imeShown, showImeSwitcher); if (hints == mNavigationIconHints) return; - mNavigationIconHints = hints; - if (!isTablet(mContext)) { - // All IME functions handled by launcher via Sysui flags for large screen - mNavigationBarView.setNavigationIconHints(hints); - } + setNavigationIconHints(hints); checkBarModes(); updateSystemUiStateFlags(); } @@ -952,15 +955,15 @@ public class NavigationBar implements View.OnAttachStateChangeListener, /** Restores the appearance and the transient saved state to {@link NavigationBar}. */ public void restoreAppearanceAndTransientState() { - final int barMode = barMode(mTransientShown, mAppearance); - mNavigationBarMode = barMode; + final int transitionMode = transitionMode(mTransientShown, mAppearance); + mTransitionMode = transitionMode; checkNavBarModes(); if (mAutoHideController != null) { mAutoHideController.touchAutoHide(); } if (mLightBarController != null) { mLightBarController.onNavigationBarAppearanceChanged(mAppearance, - true /* nbModeChanged */, barMode, false /* navbarColorManagedByIme */); + true /* nbModeChanged */, transitionMode, false /* navbarColorManagedByIme */); } } @@ -974,11 +977,11 @@ public class NavigationBar implements View.OnAttachStateChangeListener, boolean nbModeChanged = false; if (mAppearance != appearance) { mAppearance = appearance; - nbModeChanged = updateBarMode(barMode(mTransientShown, appearance)); + nbModeChanged = updateTransitionMode(transitionMode(mTransientShown, appearance)); } if (mLightBarController != null) { mLightBarController.onNavigationBarAppearanceChanged(appearance, nbModeChanged, - mNavigationBarMode, navbarColorManagedByIme); + mTransitionMode, navbarColorManagedByIme); } if (mBehavior != behavior) { mBehavior = behavior; @@ -1025,16 +1028,16 @@ public class NavigationBar implements View.OnAttachStateChangeListener, private void handleTransientChanged() { mNavigationBarView.onTransientStateChanged(mTransientShown, mTransientShownFromGestureOnSystemBar); - final int barMode = barMode(mTransientShown, mAppearance); - if (updateBarMode(barMode) && mLightBarController != null) { - mLightBarController.onNavigationBarModeChanged(barMode); + final int transitionMode = transitionMode(mTransientShown, mAppearance); + if (updateTransitionMode(transitionMode) && mLightBarController != null) { + mLightBarController.onNavigationBarModeChanged(transitionMode); } } // Returns true if the bar mode is changed. - private boolean updateBarMode(int barMode) { - if (mNavigationBarMode != barMode) { - mNavigationBarMode = barMode; + private boolean updateTransitionMode(int barMode) { + if (mTransitionMode != barMode) { + mTransitionMode = barMode; checkNavBarModes(); if (mAutoHideController != null) { mAutoHideController.touchAutoHide(); @@ -1044,7 +1047,7 @@ public class NavigationBar implements View.OnAttachStateChangeListener, return false; } - private static @TransitionMode int barMode(boolean isTransient, int appearance) { + private static @TransitionMode int transitionMode(boolean isTransient, int appearance) { final int lightsOutOpaque = APPEARANCE_LOW_PROFILE_BARS | APPEARANCE_OPAQUE_NAVIGATION_BARS; if (isTransient) { return MODE_SEMI_TRANSPARENT; @@ -1073,7 +1076,7 @@ public class NavigationBar implements View.OnAttachStateChangeListener, | StatusBarManager.DISABLE_SEARCH); if (masked != mDisabledFlags1) { mDisabledFlags1 = masked; - mNavigationBarView.setDisabledFlags(state1); + mNavigationBarView.setDisabledFlags(state1, mSysUiFlagsContainer); updateScreenPinningGestures(); } @@ -1455,24 +1458,7 @@ public class NavigationBar implements View.OnAttachStateChangeListener, mCentralSurfacesOptionalLazy.get().map(CentralSurfaces::isDeviceInteractive) .orElse(false) && mNavigationBarWindowState != WINDOW_STATE_HIDDEN; - mNavigationBarView.getBarTransitions().transitionTo(mNavigationBarMode, anim); - } - - @Override - public void onNavigationModeChanged(int mode) { - mNavBarMode = mode; - - if (!QuickStepContract.isGesturalMode(mode)) { - // Reset the override alpha - if (getBarTransitions() != null) { - getBarTransitions().setBackgroundOverrideAlpha(1f); - } - } - updateScreenPinningGestures(); - - if (!canShowSecondaryHandle()) { - resetSecondaryHandle(); - } + mNavigationBarView.getBarTransitions().transitionTo(mTransitionMode, anim); } public void disableAnimationsDuringHide(long delay) { @@ -1613,114 +1599,102 @@ public class NavigationBar implements View.OnAttachStateChangeListener, return mNavigationIconHints; } + private void setNavigationIconHints(int hints) { + if (hints == mNavigationIconHints) return; + if (!isTablet(mContext)) { + // All IME functions handled by launcher via Sysui flags for large screen + final boolean newBackAlt = (hints & StatusBarManager.NAVIGATION_HINT_BACK_ALT) != 0; + final boolean oldBackAlt = + (mNavigationIconHints & StatusBarManager.NAVIGATION_HINT_BACK_ALT) != 0; + if (newBackAlt != oldBackAlt) { + mNavigationBarView.onImeVisibilityChanged(newBackAlt); + mImeVisible = newBackAlt; + } + + mNavigationBarView.setNavigationIconHints(hints); + } + if (DEBUG) { + android.widget.Toast.makeText(mContext, + "Navigation icon hints = " + hints, + 500).show(); + } + mNavigationIconHints = hints; + } + + private final ModeChangedListener mModeChangedListener = new ModeChangedListener() { + @Override + public void onNavigationModeChanged(int mode) { + mNavBarMode = mode; + + if (!QuickStepContract.isGesturalMode(mode)) { + // Reset the override alpha + if (getBarTransitions() != null) { + getBarTransitions().setBackgroundOverrideAlpha(1f); + } + } + updateScreenPinningGestures(); + + if (!canShowSecondaryHandle()) { + resetSecondaryHandle(); + } + if (mNavigationBarView != null) { + mNavigationBarView.setNavBarMode(mode); + } + } + }; + + private final Gefingerpoken mTouchHandler = new Gefingerpoken() { + private boolean mDeadZoneConsuming; + + @Override + public boolean onInterceptTouchEvent(MotionEvent ev) { + if (isGesturalMode(mNavBarMode) && mImeVisible + && ev.getAction() == MotionEvent.ACTION_DOWN) { + SysUiStatsLog.write(SysUiStatsLog.IME_TOUCH_REPORTED, + (int) ev.getX(), (int) ev.getY()); + } + return shouldDeadZoneConsumeTouchEvents(ev); + } + + @Override + public boolean onTouchEvent(MotionEvent ev) { + shouldDeadZoneConsumeTouchEvents(ev); + return false; + } + + private boolean shouldDeadZoneConsumeTouchEvents(MotionEvent event) { + int action = event.getActionMasked(); + if (action == MotionEvent.ACTION_DOWN) { + mDeadZoneConsuming = false; + } + if (mDeadZone.onTouchEvent(event) || mDeadZoneConsuming) { + switch (action) { + case MotionEvent.ACTION_DOWN: + // Allow gestures starting in the deadzone to be slippery + mNavigationBarView.setSlippery(true); + mDeadZoneConsuming = true; + break; + case MotionEvent.ACTION_CANCEL: + case MotionEvent.ACTION_UP: + // When a gesture started in the deadzone is finished, restore + // slippery state + mNavigationBarView.updateSlippery(); + mDeadZoneConsuming = false; + break; + } + return true; + } + return false; + } + }; + + /** * Injectable factory for construction a {@link NavigationBar}. */ - public static class Factory { - private final Lazy<AssistManager> mAssistManagerLazy; - private final AccessibilityManager mAccessibilityManager; - private final DeviceProvisionedController mDeviceProvisionedController; - private final MetricsLogger mMetricsLogger; - private final OverviewProxyService mOverviewProxyService; - private final NavigationModeController mNavigationModeController; - private final AccessibilityButtonModeObserver mAccessibilityButtonModeObserver; - private final StatusBarStateController mStatusBarStateController; - private final SysUiState mSysUiFlagsContainer; - private final BroadcastDispatcher mBroadcastDispatcher; - private final CommandQueue mCommandQueue; - private final Optional<Pip> mPipOptional; - private final Optional<Recents> mRecentsOptional; - private final Lazy<Optional<CentralSurfaces>> mCentralSurfacesOptionalLazy; - private final ShadeController mShadeController; - private final NotificationRemoteInputManager mNotificationRemoteInputManager; - private final NotificationShadeDepthController mNotificationShadeDepthController; - private final Handler mMainHandler; - private final NavigationBarOverlayController mNavbarOverlayController; - private final UiEventLogger mUiEventLogger; - private final NavBarHelper mNavBarHelper; - private final LightBarController mMainLightBarController; - private final LightBarController.Factory mLightBarControllerFactory; - private final AutoHideController mMainAutoHideController; - private final AutoHideController.Factory mAutoHideControllerFactory; - private final Optional<TelecomManager> mTelecomManagerOptional; - private final InputMethodManager mInputMethodManager; - private final Optional<BackAnimation> mBackAnimation; - - @Inject - public Factory( - Lazy<AssistManager> assistManagerLazy, - AccessibilityManager accessibilityManager, - DeviceProvisionedController deviceProvisionedController, - MetricsLogger metricsLogger, - OverviewProxyService overviewProxyService, - NavigationModeController navigationModeController, - AccessibilityButtonModeObserver accessibilityButtonModeObserver, - StatusBarStateController statusBarStateController, - SysUiState sysUiFlagsContainer, - BroadcastDispatcher broadcastDispatcher, - CommandQueue commandQueue, - Optional<Pip> pipOptional, - Optional<Recents> recentsOptional, - Lazy<Optional<CentralSurfaces>> centralSurfacesOptionalLazy, - ShadeController shadeController, - NotificationRemoteInputManager notificationRemoteInputManager, - NotificationShadeDepthController notificationShadeDepthController, - @Main Handler mainHandler, - NavigationBarOverlayController navbarOverlayController, - UiEventLogger uiEventLogger, - NavBarHelper navBarHelper, - LightBarController mainLightBarController, - LightBarController.Factory lightBarControllerFactory, - AutoHideController mainAutoHideController, - AutoHideController.Factory autoHideControllerFactory, - Optional<TelecomManager> telecomManagerOptional, - InputMethodManager inputMethodManager, - Optional<BackAnimation> backAnimation) { - mAssistManagerLazy = assistManagerLazy; - mAccessibilityManager = accessibilityManager; - mDeviceProvisionedController = deviceProvisionedController; - mMetricsLogger = metricsLogger; - mOverviewProxyService = overviewProxyService; - mNavigationModeController = navigationModeController; - mAccessibilityButtonModeObserver = accessibilityButtonModeObserver; - mStatusBarStateController = statusBarStateController; - mSysUiFlagsContainer = sysUiFlagsContainer; - mBroadcastDispatcher = broadcastDispatcher; - mCommandQueue = commandQueue; - mPipOptional = pipOptional; - mRecentsOptional = recentsOptional; - mCentralSurfacesOptionalLazy = centralSurfacesOptionalLazy; - mShadeController = shadeController; - mNotificationRemoteInputManager = notificationRemoteInputManager; - mNotificationShadeDepthController = notificationShadeDepthController; - mMainHandler = mainHandler; - mNavbarOverlayController = navbarOverlayController; - mUiEventLogger = uiEventLogger; - mNavBarHelper = navBarHelper; - mMainLightBarController = mainLightBarController; - mLightBarControllerFactory = lightBarControllerFactory; - mMainAutoHideController = mainAutoHideController; - mAutoHideControllerFactory = autoHideControllerFactory; - mTelecomManagerOptional = telecomManagerOptional; - mInputMethodManager = inputMethodManager; - mBackAnimation = backAnimation; - } - + @AssistedFactory + public interface Factory { /** Construct a {@link NavigationBar} */ - public NavigationBar create(Context context) { - final WindowManager wm = context.getSystemService(WindowManager.class); - return new NavigationBar(context, wm, mAssistManagerLazy, - mAccessibilityManager, mDeviceProvisionedController, mMetricsLogger, - mOverviewProxyService, mNavigationModeController, - mAccessibilityButtonModeObserver, mStatusBarStateController, - mSysUiFlagsContainer, mBroadcastDispatcher, mCommandQueue, mPipOptional, - mRecentsOptional, mCentralSurfacesOptionalLazy, - mShadeController, mNotificationRemoteInputManager, - mNotificationShadeDepthController, mMainHandler, - mNavbarOverlayController, mUiEventLogger, mNavBarHelper, - mMainLightBarController, mLightBarControllerFactory, - mMainAutoHideController, mAutoHideControllerFactory, mTelecomManagerOptional, - mInputMethodManager, mBackAnimation); - } + NavigationBar create(Context context, WindowManager windowManager); } } diff --git a/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBarController.java b/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBarController.java index a049736a53d5..b640e1d24385 100644 --- a/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBarController.java +++ b/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBarController.java @@ -39,6 +39,7 @@ import android.util.SparseArray; import android.view.Display; import android.view.IWindowManager; import android.view.View; +import android.view.WindowManager; import android.view.WindowManagerGlobal; import androidx.annotation.NonNull; @@ -323,7 +324,8 @@ public class NavigationBarController implements final Context context = isOnDefaultDisplay ? mContext : mContext.createDisplayContext(display); - NavigationBar navBar = mNavigationBarFactory.create(context); + NavigationBar navBar = mNavigationBarFactory.create( + context, context.getSystemService(WindowManager.class)); mNavigationBars.put(displayId, navBar); diff --git a/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBarView.java b/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBarView.java index 017bbdffdc4f..f5abe28914c3 100644 --- a/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBarView.java +++ b/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBarView.java @@ -65,6 +65,7 @@ import android.widget.FrameLayout; import com.android.internal.annotations.VisibleForTesting; import com.android.settingslib.Utils; import com.android.systemui.Dependency; +import com.android.systemui.Gefingerpoken; import com.android.systemui.R; import com.android.systemui.animation.Interpolators; import com.android.systemui.model.SysUiState; @@ -84,13 +85,12 @@ import com.android.systemui.shared.rotation.RotationButton.RotationButtonUpdates import com.android.systemui.shared.rotation.RotationButtonController; import com.android.systemui.shared.system.ActivityManagerWrapper; import com.android.systemui.shared.system.QuickStepContract; -import com.android.systemui.shared.system.SysUiStatsLog; import com.android.systemui.shared.system.WindowManagerWrapper; import com.android.systemui.statusbar.CommandQueue; import com.android.systemui.statusbar.phone.AutoHideController; +import com.android.systemui.statusbar.phone.CentralSurfaces; import com.android.systemui.statusbar.phone.LightBarTransitionsController; import com.android.systemui.statusbar.phone.NotificationPanelViewController; -import com.android.systemui.statusbar.phone.CentralSurfaces; import com.android.wm.shell.back.BackAnimation; import com.android.wm.shell.pip.Pip; @@ -101,15 +101,14 @@ import java.util.Optional; import java.util.concurrent.Executor; import java.util.function.Consumer; -public class NavigationBarView extends FrameLayout implements - NavigationModeController.ModeChangedListener { +/** */ +public class NavigationBarView extends FrameLayout { final static boolean DEBUG = false; final static String TAG = "NavBarView"; final static boolean ALTERNATE_CAR_MODE_UI = false; private final RegionSamplingHelper mRegionSamplingHelper; private final int mNavColorSampleMargin; - private final SysUiState mSysUiFlagContainer; // The current view is one of mHorizontal or mVertical depending on the current configuration View mCurrentView = null; @@ -197,6 +196,7 @@ public class NavigationBarView extends FrameLayout implements * <p>Cache the value here for better performance.</p> */ private final boolean mImeCanRenderGesturalNavButtons = canImeRenderGesturalNavButtons(); + private Gefingerpoken mTouchHandler; private class NavTransitionListener implements TransitionListener { private boolean mBackTransitioning; @@ -333,10 +333,8 @@ public class NavigationBarView extends FrameLayout implements mDarkIconColor = Utils.getColorAttrDefaultColor(darkContext, R.attr.singleToneColor); mIsVertical = false; mLongClickableAccessibilityButton = false; - mNavBarMode = Dependency.get(NavigationModeController.class).addListener(this); mImeDrawsImeNavBar = Dependency.get(NavigationModeController.class).getImeDrawsImeNavBar(); - mSysUiFlagContainer = Dependency.get(SysUiState.class); // Set up the context group of buttons mContextualButtonGroup = new ContextualButtonGroup(R.id.menu_container); final ContextualButton imeSwitcherButton = new ContextualButton(R.id.ime_switcher, @@ -365,8 +363,6 @@ public class NavigationBarView extends FrameLayout implements R.drawable.ic_sysbar_rotate_button_cw_start_90, () -> getDisplay().getRotation()); - updateRotationButton(); - mOverviewProxyService = Dependency.get(OverviewProxyService.class); mConfiguration = new Configuration(); @@ -448,19 +444,18 @@ public class NavigationBarView extends FrameLayout implements notifyVerticalChangedListener(mIsVertical); } + public void setTouchHandler(Gefingerpoken touchHandler) { + mTouchHandler = touchHandler; + } + @Override public boolean onInterceptTouchEvent(MotionEvent event) { - if (isGesturalMode(mNavBarMode) && mImeVisible - && event.getAction() == MotionEvent.ACTION_DOWN) { - SysUiStatsLog.write(SysUiStatsLog.IME_TOUCH_REPORTED, - (int) event.getX(), (int) event.getY()); - } - return shouldDeadZoneConsumeTouchEvents(event) || super.onInterceptTouchEvent(event); + return mTouchHandler.onInterceptTouchEvent(event) || super.onInterceptTouchEvent(event); } @Override public boolean onTouchEvent(MotionEvent event) { - shouldDeadZoneConsumeTouchEvents(event); + mTouchHandler.onTouchEvent(event); return super.onTouchEvent(event); } @@ -497,30 +492,6 @@ public class NavigationBarView extends FrameLayout implements } } - private boolean shouldDeadZoneConsumeTouchEvents(MotionEvent event) { - int action = event.getActionMasked(); - if (action == MotionEvent.ACTION_DOWN) { - mDeadZoneConsuming = false; - } - if (mDeadZone.onTouchEvent(event) || mDeadZoneConsuming) { - switch (action) { - case MotionEvent.ACTION_DOWN: - // Allow gestures starting in the deadzone to be slippery - setSlippery(true); - mDeadZoneConsuming = true; - break; - case MotionEvent.ACTION_CANCEL: - case MotionEvent.ACTION_UP: - // When a gesture started in the deadzone is finished, restore slippery state - updateSlippery(); - mDeadZoneConsuming = false; - break; - } - return true; - } - return false; - } - public void abortCurrentGesture() { getHomeButton().abortCurrentGesture(); } @@ -589,7 +560,7 @@ public class NavigationBarView extends FrameLayout implements return (mDisabledFlags & View.STATUS_BAR_DISABLE_RECENT) == 0; } - public boolean isQuickStepSwipeUpEnabled() { + private boolean isQuickStepSwipeUpEnabled() { return mOverviewProxyService.shouldShowSwipeUpUI() && isOverviewEnabled(); } @@ -618,7 +589,7 @@ public class NavigationBarView extends FrameLayout implements /** * Updates the rotation button based on the current navigation mode. */ - private void updateRotationButton() { + void updateRotationButton() { if (isGesturalMode(mNavBarMode)) { mContextualButtonGroup.removeButton(R.id.rotate_suggestion); mButtonDispatchers.remove(R.id.rotate_suggestion); @@ -722,25 +693,13 @@ public class NavigationBarView extends FrameLayout implements super.setLayoutDirection(layoutDirection); } - public void setNavigationIconHints(int hints) { + void setNavigationIconHints(int hints) { if (hints == mNavigationIconHints) return; - final boolean newBackAlt = (hints & StatusBarManager.NAVIGATION_HINT_BACK_ALT) != 0; - final boolean oldBackAlt = - (mNavigationIconHints & StatusBarManager.NAVIGATION_HINT_BACK_ALT) != 0; - if (newBackAlt != oldBackAlt) { - onImeVisibilityChanged(newBackAlt); - } - - if (DEBUG) { - android.widget.Toast.makeText(getContext(), - "Navigation icon hints = " + hints, - 500).show(); - } mNavigationIconHints = hints; updateNavButtonIcons(); } - private void onImeVisibilityChanged(boolean visible) { + void onImeVisibilityChanged(boolean visible) { if (!visible) { mTransitionListener.onBackAltCleared(); } @@ -751,7 +710,7 @@ public class NavigationBarView extends FrameLayout implements } } - public void setDisabledFlags(int disabledFlags) { + void setDisabledFlags(int disabledFlags, SysUiState sysUiState) { if (mDisabledFlags == disabledFlags) return; final boolean overviewEnabledBefore = isOverviewEnabled(); @@ -764,7 +723,7 @@ public class NavigationBarView extends FrameLayout implements updateNavButtonIcons(); updateSlippery(); - updateDisabledSystemUiStateFlags(); + updateDisabledSystemUiStateFlags(sysUiState); } public void updateNavButtonIcons() { @@ -907,10 +866,11 @@ public class NavigationBarView extends FrameLayout implements updateSlippery(); } - public void updateDisabledSystemUiStateFlags() { + /** */ + public void updateDisabledSystemUiStateFlags(SysUiState sysUiState) { int displayId = mContext.getDisplayId(); - mSysUiFlagContainer.setFlag(SYSUI_STATE_SCREEN_PINNING, + sysUiState.setFlag(SYSUI_STATE_SCREEN_PINNING, ActivityManagerWrapper.getInstance().isScreenPinningActive()) .setFlag(SYSUI_STATE_OVERVIEW_DISABLED, (mDisabledFlags & View.STATUS_BAR_DISABLE_RECENT) != 0) @@ -952,12 +912,12 @@ public class NavigationBarView extends FrameLayout implements * slippery is enabled, touch events will leave the nav bar window and enter into the fullscreen * app/home window, if not nav bar will receive a cancelled touch event once gesture leaves bar. */ - public void updateSlippery() { + void updateSlippery() { setSlippery(!isQuickStepSwipeUpEnabled() || (mPanelView != null && mPanelView.isFullyExpanded() && !mPanelView.isCollapsing())); } - private void setSlippery(boolean slippery) { + void setSlippery(boolean slippery) { setWindowFlag(WindowManager.LayoutParams.FLAG_SLIPPERY, slippery); } @@ -979,8 +939,7 @@ public class NavigationBarView extends FrameLayout implements wm.updateViewLayout(navbarView, lp); } - @Override - public void onNavigationModeChanged(int mode) { + void setNavBarMode(int mode) { mNavBarMode = mode; mImeDrawsImeNavBar = Dependency.get(NavigationModeController.class).getImeDrawsImeNavBar(); mBarTransitions.onNavigationModeChanged(mNavBarMode); @@ -1323,7 +1282,6 @@ public class NavigationBarView extends FrameLayout implements mEdgeBackGestureHandler.onNavBarAttached(); requestApplyInsets(); reorient(); - onNavigationModeChanged(mNavBarMode); if (mRotationButtonController != null) { mRotationButtonController.registerListeners(); } @@ -1338,7 +1296,6 @@ public class NavigationBarView extends FrameLayout implements @Override protected void onDetachedFromWindow() { super.onDetachedFromWindow(); - Dependency.get(NavigationModeController.class).removeListener(this); for (int i = 0; i < mButtonDispatchers.size(); ++i) { mButtonDispatchers.valueAt(i).onDestroy(); } 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 4dacf5dfd78c..001a4628916f 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 android.view.WindowMetrics; 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 @@ public class EdgeBackGestureHandler extends CurrentUserTracker 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 @@ public class EdgeBackGestureHandler extends CurrentUserTracker 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 @@ public class EdgeBackGestureHandler extends CurrentUserTracker 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 @@ public class EdgeBackGestureHandler extends CurrentUserTracker 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 @@ public class EdgeBackGestureHandler extends CurrentUserTracker @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 @@ public class EdgeBackGestureHandler extends CurrentUserTracker 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 @@ public class EdgeBackGestureHandler extends CurrentUserTracker 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 @@ public class EdgeBackGestureHandler extends CurrentUserTracker mWindowManager = windowManager; mWindowManagerService = windowManagerService; mFalsingManager = falsingManager; + mLatencyTracker = latencyTracker; } /** Construct a {@link EdgeBackGestureHandler}. */ @@ -994,7 +1001,7 @@ public class EdgeBackGestureHandler extends CurrentUserTracker 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 a6919e826d4f..a1258df7a12c 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.FloatPropertyCompat; 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 @@ public class NavigationBarEdgePanel extends View implements NavigationEdgeBackPl 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 @@ public class NavigationBarEdgePanel extends View implements NavigationEdgeBackPl 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 @@ public class NavigationBarEdgePanel extends View implements NavigationEdgeBackPl private BackAnimation mBackAnimation; public NavigationBarEdgePanel(Context context, - BackAnimation backAnimation) { + BackAnimation backAnimation, LatencyTracker latencyTracker) { super(context); mWindowManager = context.getSystemService(WindowManager.class); @@ -383,6 +386,7 @@ public class NavigationBarEdgePanel extends View implements NavigationEdgeBackPl }, backgroundExecutor); mRegionSamplingHelper.setWindowVisible(true); mShowProtection = !isPrimaryDisplay; + mLatencyTracker = latencyTracker; } public void setBackAnimation(BackAnimation backAnimation) { @@ -492,6 +496,8 @@ public class NavigationBarEdgePanel extends View implements NavigationEdgeBackPl 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 @@ public class NavigationBarEdgePanel extends View implements NavigationEdgeBackPl 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/OngoingPrivacyChip.kt b/packages/SystemUI/src/com/android/systemui/privacy/OngoingPrivacyChip.kt index 9cd97ff8e343..2a6ca1acb38e 100644 --- a/packages/SystemUI/src/com/android/systemui/privacy/OngoingPrivacyChip.kt +++ b/packages/SystemUI/src/com/android/systemui/privacy/OngoingPrivacyChip.kt @@ -22,13 +22,14 @@ import android.widget.ImageView import android.widget.LinearLayout import com.android.settingslib.Utils import com.android.systemui.R +import com.android.systemui.statusbar.events.BackgroundAnimatableView class OngoingPrivacyChip @JvmOverloads constructor( context: Context, attrs: AttributeSet? = null, defStyleAttrs: Int = 0, defStyleRes: Int = 0 -) : FrameLayout(context, attrs, defStyleAttrs, defStyleRes) { +) : FrameLayout(context, attrs, defStyleAttrs, defStyleRes), BackgroundAnimatableView { private var iconMargin = 0 private var iconSize = 0 @@ -50,6 +51,16 @@ class OngoingPrivacyChip @JvmOverloads constructor( updateResources() } + /** + * When animating as a chip in the status bar, we want to animate the width for the container + * of the privacy items. We have to subtract our own top and left offset because the bounds + * come to us as absolute on-screen bounds, and `iconsContainer` is laid out relative to the + * frame layout's bounds. + */ + override fun setBoundsForAnimation(l: Int, t: Int, r: Int, b: Int) { + iconsContainer.setLeftTopRightBottom(l - left, t - top, r - left, b - top) + } + // Should only be called if the builder icons or app changed private fun updateView(builder: PrivacyChipBuilder) { fun setIcons(chipBuilder: PrivacyChipBuilder, iconsContainer: ViewGroup) { diff --git a/packages/SystemUI/src/com/android/systemui/privacy/PrivacyDialogController.kt b/packages/SystemUI/src/com/android/systemui/privacy/PrivacyDialogController.kt index 61071235db0b..8147877a8a29 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 @@ class PrivacyDialogController( 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 @@ class PrivacyDialogController( 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 d1b569f7f438..4640205c82f5 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 @@ public class QSAnimator implements Callback, PageListener, Listener, OnLayoutCha 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 @@ public class QSAnimator implements Callback, PageListener, Listener, OnLayoutCha 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/QSFragment.java b/packages/SystemUI/src/com/android/systemui/qs/QSFragment.java index 3ef72202a591..fe8c309ad2f3 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/QSFragment.java +++ b/packages/SystemUI/src/com/android/systemui/qs/QSFragment.java @@ -573,6 +573,7 @@ public class QSFragment extends LifecycleFragment implements QS, CommandQueue.Ca if (mQSAnimator != null) { mQSAnimator.setPosition(expansion); } + mQqsMediaHost.setSquishFraction(mSquishinessFraction); updateMediaPositions(); } diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSSecurityFooter.java b/packages/SystemUI/src/com/android/systemui/qs/QSSecurityFooter.java index 3824e1b83461..ea9bc6946ffe 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 @@ class QSSecurityFooter implements OnClickListener, DialogInterface.OnClickListen 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 @@ class QSSecurityFooter implements OnClickListener, DialogInterface.OnClickListen 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 @@ class QSSecurityFooter implements OnClickListener, DialogInterface.OnClickListen } 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 @@ class QSSecurityFooter implements OnClickListener, DialogInterface.OnClickListen 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 @@ class QSSecurityFooter implements OnClickListener, DialogInterface.OnClickListen 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 @@ class QSSecurityFooter implements OnClickListener, DialogInterface.OnClickListen 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 @@ class QSSecurityFooter implements OnClickListener, DialogInterface.OnClickListen 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 @@ class QSSecurityFooter implements OnClickListener, DialogInterface.OnClickListen } 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 @@ class QSSecurityFooter implements OnClickListener, DialogInterface.OnClickListen } 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 @@ class QSSecurityFooter implements OnClickListener, DialogInterface.OnClickListen @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 @@ class QSSecurityFooter implements OnClickListener, DialogInterface.OnClickListen 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 @@ class QSSecurityFooter implements OnClickListener, DialogInterface.OnClickListen organizationName); } } - return mDpm.getString( + return mDpm.getResources().getString( QS_DIALOG_MANAGEMENT, () -> mContext.getString(R.string.monitoring_description_management)); } @@ -680,13 +680,13 @@ class QSSecurityFooter implements OnClickListener, DialogInterface.OnClickListen 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 @@ class QSSecurityFooter implements OnClickListener, DialogInterface.OnClickListen 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 @@ class QSSecurityFooter implements OnClickListener, DialogInterface.OnClickListen 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 @@ class QSSecurityFooter implements OnClickListener, DialogInterface.OnClickListen 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 @@ class QSSecurityFooter implements OnClickListener, DialogInterface.OnClickListen } } 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 @@ class QSSecurityFooter implements OnClickListener, DialogInterface.OnClickListen 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 @@ class QSSecurityFooter implements OnClickListener, DialogInterface.OnClickListen 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 @@ class QSSecurityFooter implements OnClickListener, DialogInterface.OnClickListen 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 8c08873b9ab6..f2dd7700e65e 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 @@ public class QuickStatusBarHeader extends FrameLayout { 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/QRCodeScannerTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/QRCodeScannerTile.java index b65802506cbf..b41502213555 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/tiles/QRCodeScannerTile.java +++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/QRCodeScannerTile.java @@ -117,7 +117,6 @@ public class QRCodeScannerTile extends QSTileImpl<QSTile.State> { state.icon = ResourceIcon.get(R.drawable.ic_qr_code_scanner); state.state = mQRCodeScannerController.isEnabledForQuickSettings() ? Tile.STATE_ACTIVE : Tile.STATE_UNAVAILABLE; - state.secondaryLabel = mContext.getString(R.string.qr_code_scanner_description); } @Override 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 4279b62d54ab..7130294deccb 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 @@ public class WorkModeTile extends QSTileImpl<BooleanState> implements @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 8bad2de189c5..2cc3986c6e82 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.content.Intent; 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 @@ public class InternetAdapter extends RecyclerView.Adapter<InternetAdapter.Intern 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 d1c784457c9f..8921e95fcee9 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 @@ public class InternetDialog extends SystemUIDialog implements 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 b322cbf6c60e..d97ce7757d8c 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 @@ public class InternetDialogController implements AccessPointController.AccessPoi 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/recents/OverviewProxyService.java b/packages/SystemUI/src/com/android/systemui/recents/OverviewProxyService.java index a3dea1c68b14..53a27ff4e08b 100644 --- a/packages/SystemUI/src/com/android/systemui/recents/OverviewProxyService.java +++ b/packages/SystemUI/src/com/android/systemui/recents/OverviewProxyService.java @@ -101,8 +101,8 @@ import com.android.systemui.shared.system.ActivityManagerWrapper; import com.android.systemui.shared.system.QuickStepContract; import com.android.systemui.statusbar.CommandQueue; import com.android.systemui.statusbar.NotificationShadeWindowController; -import com.android.systemui.statusbar.phone.NotificationPanelViewController; import com.android.systemui.statusbar.phone.CentralSurfaces; +import com.android.systemui.statusbar.phone.NotificationPanelViewController; import com.android.systemui.statusbar.phone.StatusBarWindowCallback; import com.android.systemui.statusbar.policy.CallbackController; import com.android.wm.shell.back.BackAnimation; @@ -675,7 +675,7 @@ public class OverviewProxyService extends CurrentUserTracker implements navBarFragment.updateSystemUiStateFlags(); } if (navBarView != null) { - navBarView.updateDisabledSystemUiStateFlags(); + navBarView.updateDisabledSystemUiStateFlags(mSysUiState); } if (panelController != null) { panelController.updateSystemUiStateFlags(); diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardIndicationController.java b/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardIndicationController.java index ccec0c2d58cc..d51aaad46432 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 @@ public class KeyguardIndicationController { } } + /** + * 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 @@ public class KeyguardIndicationController { 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 @@ public class KeyguardIndicationController { 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 ab4d0dd355f3..4732a8c09500 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/LockscreenShadeTransitionController.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/LockscreenShadeTransitionController.kt @@ -34,11 +34,11 @@ 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.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.ConfigurationController import com.android.systemui.util.Utils import java.io.FileDescriptor @@ -116,6 +116,16 @@ class LockscreenShadeTransitionController @Inject constructor( 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 @@ class LockscreenShadeTransitionController @Inject constructor( 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 @@ class LockscreenShadeTransitionController @Inject constructor( false /* animate */, 0 /* delay */) mediaHierarchyManager.setTransitionToFullShadeAmount(field) + transitionToShadeAmountScrim(field) transitionToShadeAmountCommon(field) transitionToShadeAmountKeyguard(field) } @@ -417,10 +432,15 @@ class LockscreenShadeTransitionController @Inject constructor( 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 94a6d3e99842..66c1d87fb812 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 @@ public class NotificationRemoteInputManager implements Dumpable { 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 3dd717d2f377..eaa66bbc15ac 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 @@ public class NotificationShelf extends ActivatableNotificationView implements ? 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/PulseExpansionHandler.kt b/packages/SystemUI/src/com/android/systemui/statusbar/PulseExpansionHandler.kt index 3fe108f2c951..f0e01a33fc99 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/PulseExpansionHandler.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/PulseExpansionHandler.kt @@ -192,7 +192,10 @@ constructor( override fun onTouchEvent(event: MotionEvent): Boolean { val finishExpanding = (event.action == MotionEvent.ACTION_CANCEL || event.action == MotionEvent.ACTION_UP) && isExpanding - if (!canHandleMotionEvent() && !finishExpanding) { + + val isDraggingNotificationOrCanBypass = mStartingChild?.showingPulsing() == true || + bypassController.canBypass() + if ((!canHandleMotionEvent() || !isDraggingNotificationOrCanBypass) && !finishExpanding) { // We allow cancellations/finishing to still go through here to clean up the state return false } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarMobileView.java b/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarMobileView.java index 465ab93132f9..3013ad0070a0 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 @@ public class StatusBarMobileView extends FrameLayout implements DarkReceiver, 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/StatusEvent.kt b/packages/SystemUI/src/com/android/systemui/statusbar/events/StatusEvent.kt index d4d84c138b20..4e1404d0637b 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/events/StatusEvent.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/events/StatusEvent.kt @@ -16,6 +16,7 @@ package com.android.systemui.statusbar.events +import android.annotation.SuppressLint import android.content.Context import android.graphics.Color import android.graphics.drawable.ColorDrawable @@ -27,13 +28,15 @@ import com.android.systemui.R import com.android.systemui.privacy.OngoingPrivacyChip import com.android.systemui.privacy.PrivacyItem +typealias ViewCreator = (context: Context) -> BackgroundAnimatableView + interface StatusEvent { val priority: Int // Whether or not to force the status bar open and show a dot val forceVisible: Boolean // Whether or not to show an animation for this event val showAnimation: Boolean - val viewCreator: (context: Context) -> View + val viewCreator: ViewCreator var contentDescription: String? // Update this event with values from another event. @@ -47,14 +50,37 @@ interface StatusEvent { } } +class BGView( + context: Context +) : View(context), BackgroundAnimatableView { + override val view: View + get() = this + + override fun setBoundsForAnimation(l: Int, t: Int, r: Int, b: Int) { + setLeftTopRightBottom(l, t, r, b) + } +} + +@SuppressLint("AppCompatCustomView") +class BGImageView( + context: Context +) : ImageView(context), BackgroundAnimatableView { + override val view: View + get() = this + + override fun setBoundsForAnimation(l: Int, t: Int, r: Int, b: Int) { + setLeftTopRightBottom(l, t, r, b) + } +} + class BatteryEvent : StatusEvent { override val priority = 50 override val forceVisible = false override val showAnimation = true override var contentDescription: String? = "" - override val viewCreator: (context: Context) -> View = { context -> - val iv = ImageView(context) + override val viewCreator: (context: Context) -> BGImageView = { context -> + val iv = BGImageView(context) iv.setImageDrawable(ThemedBatteryDrawable(context, Color.WHITE)) iv.setBackgroundDrawable(ColorDrawable(Color.GREEN)) iv @@ -72,7 +98,7 @@ class PrivacyEvent(override val showAnimation: Boolean = true) : StatusEvent { var privacyItems: List<PrivacyItem> = listOf() private var privacyChip: OngoingPrivacyChip? = null - override val viewCreator: (context: Context) -> View = { context -> + override val viewCreator: ViewCreator = { context -> val v = LayoutInflater.from(context) .inflate(R.layout.ongoing_privacy_chip, null) as OngoingPrivacyChip v.privacyList = privacyItems @@ -82,7 +108,7 @@ class PrivacyEvent(override val showAnimation: Boolean = true) : StatusEvent { } override fun toString(): String { - return javaClass.simpleName + return "${javaClass.simpleName}(forceVisible=$forceVisible, privacyItems=$privacyItems)" } override fun shouldUpdateFromEvent(other: StatusEvent?): Boolean { 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 d5a0467c9b9e..b74140da99d2 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/events/SystemEventChipAnimationController.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/events/SystemEventChipAnimationController.kt @@ -16,18 +16,24 @@ 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.Rect import android.view.Gravity import android.view.LayoutInflater import android.view.View +import android.view.View.MeasureSpec.AT_MOST import android.view.ViewGroup.LayoutParams.MATCH_PARENT import android.view.ViewGroup.LayoutParams.WRAP_CONTENT import android.widget.FrameLayout import com.android.systemui.R -import com.android.systemui.statusbar.phone.StatusBarLocationPublisher +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. @@ -35,105 +41,262 @@ import javax.inject.Inject class SystemEventChipAnimationController @Inject constructor( private val context: Context, private val statusBarWindowController: StatusBarWindowController, - private val locationPublisher: StatusBarLocationPublisher -) : SystemStatusChipAnimationCallback { - var showPersistentDot = false - set(value) { - field = value - statusBarWindowController.setForceStatusBarVisible(value) - maybeUpdateShowDot() - } + private val contentInsetsProvider: StatusBarContentInsetsProvider +) : SystemStatusAnimationCallback { private lateinit var animationWindowView: FrameLayout - private lateinit var animationDotView: View - private var currentAnimatedView: View? = null + + private var currentAnimatedView: BackgroundAnimatableView? = null + + // Left for LTR, Right for RTL + private var animationDirection = LEFT + private var chipRight = 0 + private var chipLeft = 0 + private var chipWidth = 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) + // 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: (context: Context) -> View, - @SystemAnimationState state: Int - ) { - if (!initialized) init() - - if (state == ANIMATING_IN) { - currentAnimatedView = viewCreator(context) - animationWindowView.addView(currentAnimatedView, layoutParamsDefault()) - - // We are animating IN; chip comes in from View.END - currentAnimatedView?.apply { - val translation = width.toFloat() - translationX = if (isLayoutRtl) -translation else translation - alpha = 0f - visibility = View.VISIBLE - setPadding(locationPublisher.marginLeft, 0, locationPublisher.marginRight, 0) + /** + * 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 + + // 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 } - } else { - // We are animating away - currentAnimatedView?.apply { - translationX = 0f - 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 { - translationX = 0f - alpha = 1f + 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 onSystemEventAnimationFinish(hasPersistentDot: Boolean): Animator { + initializeAnimRect() + val finish = if (hasPersistentDot) { + createMoveOutAnimationForDot() } else { - // Finished animating away - currentAnimatedView?.apply { - visibility = View.INVISIBLE - } - animationWindowView.removeView(currentAnimatedView) + createMoveOutAnimationDefault() } + + finish.addListener(object : AnimatorListenerAdapter() { + override fun onAnimationEnd(animation: Animator?) { + animationWindowView.removeView(currentAnimatedView!!.view) + } + }) + + return finish } - override fun onChipAnimationUpdate( - animator: ValueAnimator, - @SystemAnimationState state: Int - ) { - // Alpha is parameterized 0,1, and translation from (width, 0) - currentAnimatedView?.apply { - val amt = animator.animatedValue as Float + 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) + } + } - alpha = amt + 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 w = width - val translation = (1 - amt) * w - translationX = if (isLayoutRtl) -translation else translation + 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 maybeUpdateShowDot() { - if (!initialized) return - if (!showPersistentDot && currentAnimatedView == null) { - animationDotView.visibility = View.INVISIBLE + 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() { initialized = true animationWindowView = LayoutInflater.from(context) .inflate(R.layout.system_event_animation_window, null) as FrameLayout - animationDotView = animationWindowView.findViewById(R.id.dot_view) val lp = FrameLayout.LayoutParams(MATCH_PARENT, MATCH_PARENT) lp.gravity = Gravity.END or Gravity.CENTER_VERTICAL statusBarWindowController.addViewToWindow(animationWindowView, lp) + animationWindowView.clipToPadding = false + animationWindowView.clipChildren = false } - private fun start() = if (animationWindowView.isLayoutRtl) right() else left() - private fun right() = locationPublisher.marginRight - private fun left() = locationPublisher.marginLeft + private fun layoutParamsDefault(marginEnd: Int): FrameLayout.LayoutParams = + FrameLayout.LayoutParams(WRAP_CONTENT, WRAP_CONTENT).also { + it.gravity = Gravity.END or Gravity.CENTER_VERTICAL + it.marginEnd = marginEnd + } + + 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 -> { + animRect.set((chipRight - width), animRect.top, chipRight, animRect.bottom) + } else /* RIGHT */ -> { + animRect.set(chipLeft, animRect.top, (chipLeft + width), animRect.bottom) + } + } - private fun layoutParamsDefault(): FrameLayout.LayoutParams = - FrameLayout.LayoutParams(WRAP_CONTENT, WRAP_CONTENT).also { - it.gravity = Gravity.END or Gravity.CENTER_VERTICAL - it.marginStart = start() + updateCurrentAnimatedView() + } + + /** + * 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 + ) } } + +/** + * Chips should provide a view that can be animated with something better than a fade-in + */ +interface BackgroundAnimatableView { + val view: View // Since this can't extend View, add a view prop + get() = this as View + val chipWidth: Int + get() = view.measuredWidth + fun setBoundsForAnimation(l: Int, t: Int, r: Int, b: Int) +} + +// Animation directions +private const val LEFT = 1 +private const val RIGHT = 2 diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/events/SystemEventCoordinator.kt b/packages/SystemUI/src/com/android/systemui/statusbar/events/SystemEventCoordinator.kt index 04f7492e8562..fde5d39db7e3 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/events/SystemEventCoordinator.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/events/SystemEventCoordinator.kt @@ -70,11 +70,11 @@ class SystemEventCoordinator @Inject constructor( fun notifyPrivacyItemsChanged(showAnimation: Boolean = true) { val event = PrivacyEvent(showAnimation) event.privacyItems = privacyStateListener.currentPrivacyItems - event.contentDescription = { + event.contentDescription = run { val items = PrivacyChipBuilder(context, event.privacyItems).joinTypes() context.getString( R.string.ongoing_privacy_chip_content_multiple_apps, items) - }() + } scheduler.onStatusEvent(event) } 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 5a273294e87c..36233e4e3eab 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/events/SystemStatusAnimationScheduler.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/events/SystemStatusAnimationScheduler.kt @@ -19,13 +19,11 @@ package com.android.systemui.statusbar.events import android.animation.Animator import android.animation.AnimatorListenerAdapter import android.animation.AnimatorSet -import android.animation.ValueAnimator import android.annotation.IntDef -import android.content.Context import android.os.Process import android.provider.DeviceConfig import android.util.Log -import android.view.View +import android.view.animation.PathInterpolator import com.android.systemui.Dumpable import com.android.systemui.dagger.SysUISingleton @@ -38,6 +36,7 @@ import com.android.systemui.util.concurrency.DelayableExecutor import com.android.systemui.util.time.SystemClock import java.io.FileDescriptor import java.io.PrintWriter +import java.lang.IllegalStateException import javax.inject.Inject @@ -45,7 +44,7 @@ import javax.inject.Inject * Dead-simple scheduler for system status events. Obeys the following principles (all values TBD): * - Avoiding log spam by only allowing 12 events per minute (1event/5s) * - Waits 100ms to schedule any event for debouncing/prioritization - * - Simple prioritization: Privacy > Battery > connectivity (encoded in StatusEvent) + * - Simple prioritization: Privacy > Battery > connectivity (encoded in [StatusEvent]) * - Only schedules a single event, and throws away lowest priority events * * There are 4 basic stages of animation at play here: @@ -111,12 +110,15 @@ class SystemStatusAnimationScheduler @Inject constructor( scheduleEvent(event) } else if (scheduledEvent?.shouldUpdateFromEvent(event) == true) { if (DEBUG) { - Log.d(TAG, "updating current event from: $event") + Log.d(TAG, "updating current event from: $event. animationState=$animationState") } 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,60 +164,90 @@ class SystemStatusAnimationScheduler @Inject constructor( return } - // Schedule the animation to start after a debounce period - cancelExecutionRunnable = executor.executeDelayed({ - cancelExecutionRunnable = null - animationState = ANIMATING_IN - statusBarWindowController.setForceStatusBarVisible(true) - - val entranceAnimator = ValueAnimator.ofFloat(1f, 0f) - entranceAnimator.duration = ENTRANCE_ANIM_LENGTH - entranceAnimator.addListener(systemAnimatorAdapter) - entranceAnimator.addUpdateListener(systemUpdateListener) - - val chipAnimator = ValueAnimator.ofFloat(0f, 1f) - chipAnimator.duration = CHIP_ANIM_LENGTH - chipAnimator.addListener( - ChipAnimatorAdapter(RUNNING_CHIP_ANIM, scheduledEvent!!.viewCreator)) - chipAnimator.addUpdateListener(chipUpdateListener) - - 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) - - val chipAnimator = ValueAnimator.ofFloat(1f, 0f) - chipAnimator.duration = CHIP_ANIM_LENGTH - val endState = if (hasPersistentDot) { - SHOWING_PERSISTENT_DOT - } else { - IDLE + chipAnimationController.prepareChipAnimation(scheduledEvent!!.viewCreator) + animationState = ANIMATION_QUEUED + executor.executeDelayed({ + runChipAnimation() + }, DEBOUNCE_DELAY) + } + + /** + * 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 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() + + 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 + } + + statusBarWindowController.setForceStatusBarVisible(false) } - chipAnimator.addListener( - ChipAnimatorAdapter(endState, scheduledEvent!!.viewCreator)) - chipAnimator.addUpdateListener(chipUpdateListener) + }) + 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) + } - statusBarWindowController.setForceStatusBarVisible(false) - scheduledEvent = null - }, DISPLAY_LENGTH) - }, DELAY) + return animSet } private fun notifyTransitionToPersistentDot(): Animator? { @@ -249,18 +281,6 @@ class SystemStatusAnimationScheduler @Inject constructor( 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() @@ -279,24 +299,6 @@ class SystemStatusAnimationScheduler @Inject constructor( } } - 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") @@ -310,24 +312,6 @@ class SystemStatusAnimationScheduler @Inject constructor( } } } - - inner class ChipAnimatorAdapter( - @SystemAnimationState val endState: Int, - val viewCreator: (context: Context) -> View - ) : 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) - } - } } /** @@ -336,16 +320,14 @@ class SystemStatusAnimationScheduler @Inject constructor( * 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 @@ -355,50 +337,61 @@ interface SystemStatusAnimationCallback { @JvmDefault fun onHidePersistentDot(): Animator? { return null } } -interface SystemStatusChipAnimationCallback { - fun onChipAnimationUpdate(animator: ValueAnimator, @SystemAnimationState state: Int) {} - - fun onChipAnimationStart( - viewCreator: (context: Context) -> View, - @SystemAnimationState state: Int - ) {} - - fun onChipAnimationEnd(@SystemAnimationState state: Int) {} -} - /** + * Animation state IntDef */ @Retention(AnnotationRetention.SOURCE) @IntDef( value = [ - IDLE, ANIMATING_IN, RUNNING_CHIP_ANIM, ANIMATING_OUT + 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 7fbb0f1182c0..02aa1f2fd585 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 @@ class NotificationLaunchAnimatorControllerProvider @Inject constructor( @JvmOverloads fun getAnimatorController( notification: ExpandableNotificationRow, - onFinishAnimationCallback: Runnable = Runnable {} + onFinishAnimationCallback: Runnable? = null ): NotificationLaunchAnimatorController { return NotificationLaunchAnimatorController( notificationShadeWindowViewController, @@ -49,7 +49,7 @@ class NotificationLaunchAnimatorController( 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 @@ class NotificationLaunchAnimatorController( if (!willAnimate) { removeHun(animate = true) - onFinishAnimationCallback.run() + onFinishAnimationCallback?.run() } } @@ -142,7 +142,7 @@ class NotificationLaunchAnimatorController( notificationShadeWindowViewController.setExpandAnimationRunning(false) notificationEntry.isExpandAnimationRunning = false removeHun(animate = true) - onFinishAnimationCallback.run() + onFinishAnimationCallback?.run() } override fun onLaunchAnimationStart(isExpandingFullyAbove: Boolean) { @@ -162,7 +162,7 @@ class NotificationLaunchAnimatorController( 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/collection/coordinator/VisualStabilityCoordinator.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/VisualStabilityCoordinator.java index 699c4e77321e..acc493d4b992 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/VisualStabilityCoordinator.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/VisualStabilityCoordinator.java @@ -254,10 +254,14 @@ public class VisualStabilityCoordinator implements Coordinator, Dumpable, @Override public void dump(@NonNull FileDescriptor fd, @NonNull PrintWriter pw, @NonNull String[] args) { + pw.println("pipelineRunAllowed: " + mPipelineRunAllowed); + pw.println(" notifPanelCollapsing: " + mNotifPanelCollapsing); + pw.println(" launchingNotifActivity: " + mNotifPanelLaunchingActivity); pw.println("reorderingAllowed: " + mReorderingAllowed); pw.println(" screenOn: " + mScreenOn); pw.println(" panelExpanded: " + mPanelExpanded); pw.println(" pulsing: " + mPulsing); + pw.println("isSuppressingPipelineRun: " + mIsSuppressingPipelineRun); pw.println("isSuppressingGroupChange: " + mIsSuppressingGroupChange); pw.println("isSuppressingEntryReorder: " + mIsSuppressingEntryReorder); pw.println("entriesWithSuppressedSectionChange: " diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/render/ShadeViewDiffer.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/render/ShadeViewDiffer.kt index 386e2d31380c..032e6784ae08 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/render/ShadeViewDiffer.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/render/ShadeViewDiffer.kt @@ -18,7 +18,6 @@ package com.android.systemui.statusbar.notification.collection.render import android.annotation.MainThread import android.view.View -import com.android.systemui.util.kotlin.transform import com.android.systemui.util.traceSection /** @@ -41,7 +40,6 @@ class ShadeViewDiffer( ) { private val rootNode = ShadeNode(rootController) private val nodes = mutableMapOf(rootController to rootNode) - private val views = mutableMapOf<View, ShadeNode>() /** * Adds and removes views from the root (and its children) until their structure matches the @@ -66,26 +64,25 @@ class ShadeViewDiffer( * * For debugging purposes. */ - fun getViewLabel(view: View): String = views[view]?.label ?: view.toString() - - private fun detachChildren( - parentNode: ShadeNode, - specMap: Map<NodeController, NodeSpec> - ) { - val parentSpec = specMap[parentNode.controller] - - for (i in parentNode.getChildCount() - 1 downTo 0) { - val childView = parentNode.getChildAt(i) - views[childView]?.let { childNode -> - val childSpec = specMap[childNode.controller] - - maybeDetachChild(parentNode, parentSpec, childNode, childSpec) - - if (childNode.controller.getChildCount() > 0) { - detachChildren(childNode, specMap) + fun getViewLabel(view: View): String = + nodes.values.firstOrNull { node -> node.view === view }?.label ?: view.toString() + + private fun detachChildren(parentNode: ShadeNode, specMap: Map<NodeController, NodeSpec>) { + val views = nodes.values.asSequence().map { node -> node.view to node }.toMap() + fun detachRecursively(parentNode: ShadeNode, specMap: Map<NodeController, NodeSpec>) { + val parentSpec = specMap[parentNode.controller] + for (i in parentNode.getChildCount() - 1 downTo 0) { + val childView = parentNode.getChildAt(i) + views[childView]?.let { childNode -> + val childSpec = specMap[childNode.controller] + maybeDetachChild(parentNode, parentSpec, childNode, childSpec) + if (childNode.controller.getChildCount() > 0) { + detachRecursively(childNode, specMap) + } } } } + detachRecursively(parentNode, specMap) } private fun maybeDetachChild( @@ -94,14 +91,13 @@ class ShadeViewDiffer( childNode: ShadeNode, childSpec: NodeSpec? ) { - val newParentNode = transform(childSpec?.parent) { getNode(it) } + val newParentNode = childSpec?.parent?.let { getNode(it) } if (newParentNode != parentNode) { val childCompletelyRemoved = newParentNode == null if (childCompletelyRemoved) { nodes.remove(childNode.controller) - views.remove(childNode.controller.view) } logger.logDetachingChild( @@ -115,10 +111,7 @@ class ShadeViewDiffer( } } - private fun attachChildren( - parentNode: ShadeNode, - specMap: Map<NodeController, NodeSpec> - ) { + private fun attachChildren(parentNode: ShadeNode, specMap: Map<NodeController, NodeSpec>) { val parentSpec = checkNotNull(specMap[parentNode.controller]) for ((index, childSpec) in parentSpec.children.withIndex()) { @@ -160,7 +153,6 @@ class ShadeViewDiffer( if (node == null) { node = ShadeNode(spec.controller) nodes[node.controller] = node - views[node.view] = node } return node } @@ -194,10 +186,9 @@ class ShadeViewDiffer( private class DuplicateNodeException(message: String) : RuntimeException(message) -private class ShadeNode( - val controller: NodeController -) { - val view = controller.view +private class ShadeNode(val controller: NodeController) { + val view: View + get() = controller.view var parent: ShadeNode? = null 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 fca2aa167e37..577d536262b2 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 @@ public abstract class ActivatableNotificationView extends ExpandableOutlineView } /** - * @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 c237e1deeae3..e479509247d3 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.logging.nano.MetricsProto.MetricsEvent; 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.NotificationMenuRowPlugin.MenuItem 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.ExpandableViewState; 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 @@ public class ExpandableNotificationRow extends ActivatableNotificationView 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 @@ public class ExpandableNotificationRow extends ActivatableNotificationView 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 @@ public class ExpandableNotificationRow extends ActivatableNotificationView } 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 @@ public class ExpandableNotificationRow extends ActivatableNotificationView addView(mMenuRow.getMenuView(), menuIndex); } for (NotificationContentView l : mLayouts) { - l.initView(); + l.reinflate(); l.reInflateViews(); } mEntry.getSbn().clearPackageContext(); @@ -1464,7 +1464,7 @@ public class ExpandableNotificationRow extends ActivatableNotificationView * @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 @@ public class ExpandableNotificationRow extends ActivatableNotificationView 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 @@ public class ExpandableNotificationRow extends ActivatableNotificationView 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 @@ public class ExpandableNotificationRow extends ActivatableNotificationView 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 c4beb5bf4d7b..599039d46556 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 android.view.ViewGroup; 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.NotificationMenuRowPlugin; 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.row.dagger.NotificationRowSco 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 @@ public class ExpandableNotificationRowController implements NotifViewController 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 @@ public class ExpandableNotificationRowController implements NotifViewController 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 @@ public class ExpandableNotificationRowController implements NotifViewController mPeopleNotificationIdentifier = peopleNotificationIdentifier; mBubblesManagerOptional = bubblesManagerOptional; mDragController = dragController; + mMetricsLogger = metricsLogger; + mSmartReplyConstants = smartReplyConstants; + mSmartReplyController = smartReplyController; } /** @@ -179,7 +191,10 @@ public class ExpandableNotificationRowController implements NotifViewController 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 9cb5dc5d4aa4..b9c7113206df 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.ImageView; 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 @@ public class NotificationContentView extends FrameLayout implements Notification 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 @@ public class NotificationContentView extends FrameLayout implements Notification 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 @@ public class NotificationContentView extends FrameLayout implements Notification 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 @@ public class NotificationContentView extends FrameLayout implements Notification 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 class NotificationContentView extends FrameLayout implements Notification 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 @@ public class NotificationContentView extends FrameLayout implements Notification 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 @@ public class NotificationContentView extends FrameLayout implements Notification 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 @@ public class NotificationContentView extends FrameLayout implements Notification 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 @@ public class NotificationContentView extends FrameLayout implements Notification // 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 class NotificationContentView extends FrameLayout implements Notification } public void setGroupMembershipManager(GroupMembershipManager groupMembershipManager) { - mGroupMembershipManager = groupMembershipManager; } public void setRemoteInputController(RemoteInputController r) { @@ -1687,10 +1696,6 @@ public class NotificationContentView extends FrameLayout implements Notification mContainingNotification = containingNotification; } - public void setPeopleNotificationIdentifier(PeopleNotificationIdentifier peopleIdentifier) { - mPeopleIdentifier = peopleIdentifier; - } - public void requestSelectLayout(boolean needsAnimation) { selectLayout(needsAnimation, false); } @@ -1858,7 +1863,6 @@ public class NotificationContentView extends FrameLayout implements Notification } public void setIsLowPriority(boolean isLowPriority) { - mIsLowPriority = isLowPriority; } public boolean isDimmable() { @@ -2083,10 +2087,6 @@ public class NotificationContentView extends FrameLayout implements Notification 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 5b9dbd0f3361..c89f4d797819 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 @@ public class NotificationStackScrollLayout extends ViewGroup implements Dumpable 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 @@ public class NotificationStackScrollLayout extends ViewGroup implements Dumpable 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 @@ public class NotificationStackScrollLayout extends ViewGroup implements Dumpable } 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 @@ public class NotificationStackScrollLayout extends ViewGroup implements Dumpable } 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 @@ public class NotificationStackScrollLayout extends ViewGroup implements Dumpable 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; } @@ -1332,12 +1351,7 @@ public class NotificationStackScrollLayout extends ViewGroup implements Dumpable */ @ShadeViewRefactor(RefactorComponent.COORDINATOR) public void setExpandedHeight(float height) { - final float shadeBottom = getHeight() - getEmptyBottomMargin(); final boolean skipHeightUpdate = shouldSkipHeightUpdate(); - if (!skipHeightUpdate) { - final float expansionFraction = MathUtils.saturate(height / shadeBottom); - mAmbientState.setExpansionFraction(expansionFraction); - } updateStackPosition(); if (!skipHeightUpdate) { @@ -2245,48 +2259,10 @@ public class NotificationStackScrollLayout extends ViewGroup implements Dumpable @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 @@ -4929,6 +4905,15 @@ public class NotificationStackScrollLayout extends ViewGroup implements Dumpable 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 6bbecc8438bc..d98f8a77cc8d 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 @@ public class NotificationStackScrollLayoutController { 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 @@ public class NotificationStackScrollLayoutController { 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 @@ public class NotificationStackScrollLayoutController { ShadeController shadeController, InteractionJankMonitor jankMonitor, StackStateLogger stackLogger, - NotificationStackScrollLogger logger) { + NotificationStackScrollLogger logger, + NotificationStackSizeCalculator notificationStackSizeCalculator) { mStackStateLogger = stackLogger; mLogger = logger; mAllowLongPress = allowLongPress; @@ -688,6 +691,7 @@ public class NotificationStackScrollLayoutController { mCentralSurfaces = centralSurfaces; mScrimController = scrimController; mJankMonitor = jankMonitor; + mNotificationStackSizeCalculator = notificationStackSizeCalculator; groupManager.registerGroupExpansionChangeListener( (changedRow, expanded) -> mView.onGroupExpandChanged(changedRow, expanded)); legacyGroupManager.registerGroupChangeListener(new OnGroupChangeListener() { @@ -758,7 +762,7 @@ public class NotificationStackScrollLayoutController { }); } - mView.initView(mView.getContext(), mSwipeHelper); + mView.initView(mView.getContext(), mSwipeHelper, mNotificationStackSizeCalculator); mView.setKeyguardBypassEnabled(mKeyguardBypassController.getBypassEnabled()); mKeyguardBypassController .registerOnBypassStateChangedListener(mView::setKeyguardBypassEnabled); @@ -907,6 +911,13 @@ public class NotificationStackScrollLayoutController { 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 @@ public class NotificationStackScrollLayoutController { * 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 000000000000..3f97155242b4 --- /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 952cd9ae69bc..e1f8c35c3755 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 @@ public class StackScrollAlgorithm { 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/BiometricUnlockController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/BiometricUnlockController.java index 4bf944ae13c9..b46ed57fb866 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/BiometricUnlockController.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/BiometricUnlockController.java @@ -357,7 +357,7 @@ public class BiometricUnlockController extends KeyguardUpdateMonitorCallback imp } Trace.beginSection("BiometricUnlockController#onBiometricAcquired"); releaseBiometricWakeLock(); - if (isWakeAndUnlock()) { + if (mStatusBarStateController.isDozing()) { if (mLatencyTracker.isEnabled()) { int action = LatencyTracker.ACTION_FINGERPRINT_WAKE_AND_UNLOCK; if (biometricSourceType == BiometricSourceType.FACE) { diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfaces.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfaces.java index ec2d608b2683..6a7e8eb5446b 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfaces.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfaces.java @@ -1695,12 +1695,20 @@ public class CentralSurfaces extends CoreStartable implements public void startActivity(Intent intent, boolean dismissShade, @Nullable ActivityLaunchAnimator.Controller animationController, boolean showOverLockscreenWhenLocked) { + startActivity(intent, dismissShade, animationController, showOverLockscreenWhenLocked, + UserHandle.CURRENT); + } + + @Override + public void startActivity(Intent intent, boolean dismissShade, + @Nullable ActivityLaunchAnimator.Controller animationController, + boolean showOverLockscreenWhenLocked, UserHandle userHandle) { // Make sure that we dismiss the keyguard if it is directly dismissable or when we don't // want to show the activity above it. if (mKeyguardStateController.isUnlocked() || !showOverLockscreenWhenLocked) { startActivityDismissingKeyguard(intent, false, dismissShade, - false /* disallowEnterPictureInPictureWhileLaunching */, null /* callback */, - 0 /* flags */, animationController); + false /* disallowEnterPictureInPictureWhileLaunching */, null /* callback */, + 0 /* flags */, animationController, userHandle); return; } @@ -1755,7 +1763,7 @@ public class CentralSurfaces extends CoreStartable implements .create(mContext) .addNextIntent(intent) .startActivities(getActivityOptions(getDisplayId(), adapter), - UserHandle.CURRENT)); + userHandle)); } /** @@ -1775,7 +1783,7 @@ public class CentralSurfaces extends CoreStartable implements public void startActivity(Intent intent, boolean dismissShade, Callback callback) { startActivityDismissingKeyguard(intent, false, dismissShade, false /* disallowEnterPictureInPictureWhileLaunching */, callback, 0, - null /* animationController */); + null /* animationController */, UserHandle.CURRENT); } public void setQsExpanded(boolean expanded) { @@ -2417,7 +2425,7 @@ public class CentralSurfaces extends CoreStartable implements boolean dismissShade, int flags) { startActivityDismissingKeyguard(intent, onlyProvisioned, dismissShade, false /* disallowEnterPictureInPictureWhileLaunching */, null /* callback */, - flags, null /* animationController */); + flags, null /* animationController */, UserHandle.CURRENT); } public void startActivityDismissingKeyguard(final Intent intent, boolean onlyProvisioned, @@ -2428,7 +2436,8 @@ public class CentralSurfaces extends CoreStartable implements void startActivityDismissingKeyguard(final Intent intent, boolean onlyProvisioned, final boolean dismissShade, final boolean disallowEnterPictureInPictureWhileLaunching, final Callback callback, int flags, - @Nullable ActivityLaunchAnimator.Controller animationController) { + @Nullable ActivityLaunchAnimator.Controller animationController, + final UserHandle userHandle) { if (onlyProvisioned && !mDeviceProvisionedController.isDeviceProvisioned()) return; final boolean willLaunchResolverActivity = @@ -2487,7 +2496,7 @@ public class CentralSurfaces extends CoreStartable implements intent, intent.resolveTypeIfNeeded(mContext.getContentResolver()), null, null, 0, Intent.FLAG_ACTIVITY_NEW_TASK, null, - options.toBundle(), UserHandle.CURRENT.getIdentifier()); + options.toBundle(), userHandle.getIdentifier()); } catch (RemoteException e) { Log.w(TAG, "Unable to start activity", e); } @@ -2860,7 +2869,8 @@ public class CentralSurfaces extends CoreStartable implements false /* disallowEnterPictureInPictureWhileLaunching */, null /* callback */, 0 /* flags */, - animationController), + animationController, + UserHandle.CURRENT), delay); } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfacesCommandQueueCallbacks.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfacesCommandQueueCallbacks.java index 536be1c1a866..c4e655a45ca6 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfacesCommandQueueCallbacks.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfacesCommandQueueCallbacks.java @@ -371,7 +371,7 @@ public class CentralSurfacesCommandQueueCallbacks implements CommandQueue.Callba mCentralSurfaces.startActivityDismissingKeyguard(cameraIntent, false /* onlyProvisioned */, true /* dismissShade */, true /* disallowEnterPictureInPictureWhileLaunching */, null /* callback */, 0, - null /* animationController */); + null /* animationController */, UserHandle.CURRENT); } else { if (!mCentralSurfaces.isDeviceInteractive()) { // Avoid flickering of the scrim when we instant launch the camera and the bouncer @@ -428,7 +428,7 @@ public class CentralSurfacesCommandQueueCallbacks implements CommandQueue.Callba mCentralSurfaces.startActivityDismissingKeyguard(emergencyIntent, false /* onlyProvisioned */, true /* dismissShade */, true /* disallowEnterPictureInPictureWhileLaunching */, null /* callback */, 0, - null /* animationController */); + null /* animationController */, UserHandle.CURRENT); return; } 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 732e5f0343a2..602d075b167d 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 static com.android.systemui.statusbar.notification.NotificationUtils.inte 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 @@ public class KeyguardClockPositionAlgorithm { 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 571c10b3800f..64b0b4e2909f 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 @@ class KeyguardLiftController constructor( } } - override fun onDozingChanged(isDozing: Boolean) { - updateListeningState() - } + private val keyguardUpdateMonitorCallback = object : KeyguardUpdateMonitorCallback() { + override fun onKeyguardBouncerChanged(bouncer: Boolean) { + bouncerVisible = bouncer + updateListeningState() + } - override fun onKeyguardBouncerChanged(bouncer: Boolean) { - bouncerVisible = bouncer - updateListeningState() + override fun onKeyguardVisibilityChanged(showing: Boolean) { + 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 65173a230871..cb332bdf59b1 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 @@ public class KeyguardStatusBarView extends RelativeLayout { } private void updateKeyguardStatusBarHeight() { - MarginLayoutParams lp = (MarginLayoutParams) getLayoutParams(); + MarginLayoutParams lp = (MarginLayoutParams) getLayoutParams(); lp.height = getStatusBarHeaderHeightKeyguard(mContext); setLayoutParams(lp); } @@ -510,28 +510,6 @@ public class KeyguardStatusBarView extends RelativeLayout { } } - 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 1df1aff38593..a70ba8236e9a 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.AnimatableProperty; 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 com.android.systemui.util.ViewController; 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 @@ public class KeyguardStatusBarViewController extends ViewController<KeyguardStat @Override public void onDensityOrFontScaleChanged() { mView.loadDimens(); + // The animator is dependent on resources for offsets + mSystemEventAnimator = new StatusBarSystemEventAnimator(mView, getResources()); } @Override @@ -123,21 +123,16 @@ public class KeyguardStatusBarViewController extends ViewController<KeyguardStat 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 @@ public class KeyguardStatusBarViewController extends ViewController<KeyguardStat private int mStatusBarState; private boolean mDozing; private boolean mShowingKeyguardHeadsUp; + private StatusBarSystemEventAnimator mSystemEventAnimator; @Inject public KeyguardStatusBarViewController( @@ -292,16 +288,15 @@ public class KeyguardStatusBarViewController extends ViewController<KeyguardStat ); 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/MultiUserSwitchController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/MultiUserSwitchController.java index 324d47eed1db..799e5feb1586 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/MultiUserSwitchController.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/MultiUserSwitchController.java @@ -19,6 +19,7 @@ package com.android.systemui.statusbar.phone; import static com.android.systemui.DejankUtils.whitelistIpcs; import android.content.Intent; +import android.os.UserHandle; import android.os.UserManager; import android.view.View; import android.view.ViewGroup; @@ -62,7 +63,7 @@ public class MultiUserSwitchController extends ViewController<MultiUserSwitch> { mActivityStarter.startActivity(intent, true /* dismissShade */, ActivityLaunchAnimator.Controller.fromView(v, null), - true /* showOverlockscreenwhenlocked */); + true /* showOverlockscreenwhenlocked */, UserHandle.SYSTEM); } else { mUserSwitchDialogController.showDialog(v); } 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 cbdf5c8017c6..5746ffb6debe 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.GestureRecorder; 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.PropertyAnimator; 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 @@ public class NotificationPanelViewController extends PanelViewController { 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 @@ public class NotificationPanelViewController extends PanelViewController { 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 @@ public class NotificationPanelViewController extends PanelViewController { 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 @@ public class NotificationPanelViewController extends PanelViewController { 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 @@ public class NotificationPanelViewController extends PanelViewController { mNotificationPanelUnfoldAnimationController; private final NotificationListContainer mNotificationListContainer; + private final NotificationStackSizeCalculator mNotificationStackSizeCalculator; private View.AccessibilityDelegate mAccessibilityDelegate = new View.AccessibilityDelegate() { @Override @@ -695,7 +689,6 @@ public class NotificationPanelViewController extends PanelViewController { DynamicPrivacyController dynamicPrivacyController, KeyguardBypassController bypassController, FalsingManager falsingManager, FalsingCollector falsingCollector, - NotificationLockscreenUserManager notificationLockscreenUserManager, NotificationEntryManager notificationEntryManager, KeyguardStateController keyguardStateController, StatusBarStateController statusBarStateController, @@ -721,7 +714,6 @@ public class NotificationPanelViewController extends PanelViewController { KeyguardUserSwitcherComponent.Factory keyguardUserSwitcherComponentFactory, KeyguardStatusBarViewComponent.Factory keyguardStatusBarViewComponentFactory, LockscreenShadeTransitionController lockscreenShadeTransitionController, - NotificationGroupManagerLegacy groupManager, NotificationIconAreaController notificationIconAreaController, AuthController authController, ScrimController scrimController, @@ -753,7 +745,8 @@ public class NotificationPanelViewController extends PanelViewController { SysUiState sysUiState, KeyguardUnlockAnimationController keyguardUnlockAnimationController, NotificationListContainer notificationListContainer, - PanelEventsEmitter panelEventsEmitter) { + PanelEventsEmitter panelEventsEmitter, + NotificationStackSizeCalculator notificationStackSizeCalculator) { super(view, falsingManager, dozeLog, @@ -785,9 +778,9 @@ public class NotificationPanelViewController extends PanelViewController { mStatusBarKeyguardViewManager = statusBarKeyguardViewManager; mNotificationsQSContainerController = notificationsQSContainerController; mNotificationListContainer = notificationListContainer; + mNotificationStackSizeCalculator = notificationStackSizeCalculator; mNotificationsQSContainerController.init(); mNotificationStackScrollLayoutController = notificationStackScrollLayoutController; - mGroupManager = groupManager; mNotificationIconAreaController = notificationIconAreaController; mKeyguardStatusViewComponentFactory = keyguardStatusViewComponentFactory; mKeyguardStatusBarViewComponentFactory = keyguardStatusBarViewComponentFactory; @@ -849,7 +842,6 @@ public class NotificationPanelViewController extends PanelViewController { }); mBottomAreaShadeAlphaAnimator.setDuration(160); mBottomAreaShadeAlphaAnimator.setInterpolator(Interpolators.ALPHA_OUT); - mLockscreenUserManager = notificationLockscreenUserManager; mEntryManager = notificationEntryManager; mConversationNotificationManager = conversationNotificationManager; mAuthController = authController; @@ -874,7 +866,6 @@ public class NotificationPanelViewController extends PanelViewController { 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 @@ public class NotificationPanelViewController extends PanelViewController { 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 @@ public class NotificationPanelViewController extends PanelViewController { * @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() { @@ -3009,9 +2913,7 @@ public class NotificationPanelViewController extends PanelViewController { } private int calculatePanelHeightShade() { - int emptyBottomMargin = mNotificationStackScrollLayoutController.getEmptyBottomMargin(); - int maxHeight = mNotificationStackScrollLayoutController.getHeight() - emptyBottomMargin; - + final int maxHeight = mNotificationStackScrollLayoutController.getHeight(); if (mBarState == KEYGUARD) { int minKeyguardPanelBottom = mClockPositionAlgorithm.getLockscreenStatusViewHeight() + mNotificationStackScrollLayoutController.getIntrinsicContentHeight(); @@ -4885,6 +4787,8 @@ public class NotificationPanelViewController extends PanelViewController { "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/NotificationsQSContainerController.kt b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationsQSContainerController.kt index 7764d33856ca..a15feeb9cda8 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationsQSContainerController.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationsQSContainerController.kt @@ -4,6 +4,7 @@ import android.view.View import android.view.ViewGroup import android.view.ViewGroup.LayoutParams.WRAP_CONTENT import android.view.WindowInsets +import androidx.annotation.VisibleForTesting import androidx.constraintlayout.widget.ConstraintSet import androidx.constraintlayout.widget.ConstraintSet.BOTTOM import androidx.constraintlayout.widget.ConstraintSet.END @@ -11,6 +12,7 @@ import androidx.constraintlayout.widget.ConstraintSet.PARENT_ID import androidx.constraintlayout.widget.ConstraintSet.START import androidx.constraintlayout.widget.ConstraintSet.TOP import com.android.systemui.R +import com.android.systemui.dagger.qualifiers.Main import com.android.systemui.flags.FeatureFlags import com.android.systemui.flags.Flags import com.android.systemui.navigationbar.NavigationModeController @@ -21,14 +23,19 @@ import com.android.systemui.recents.OverviewProxyService.OverviewProxyListener import com.android.systemui.shared.system.QuickStepContract import com.android.systemui.util.Utils import com.android.systemui.util.ViewController +import com.android.systemui.util.concurrency.DelayableExecutor import java.util.function.Consumer import javax.inject.Inject +@VisibleForTesting +internal const val INSET_DEBOUNCE_MILLIS = 500L + class NotificationsQSContainerController @Inject constructor( view: NotificationsQuickSettingsContainer, private val navigationModeController: NavigationModeController, private val overviewProxyService: OverviewProxyService, - private val featureFlags: FeatureFlags + private val featureFlags: FeatureFlags, + @Main private val delayableExecutor: DelayableExecutor ) : ViewController<NotificationsQuickSettingsContainer>(view), QSContainerController { var qsExpanded = false @@ -60,11 +67,29 @@ class NotificationsQSContainerController @Inject constructor( taskbarVisible = visible } } - private val windowInsetsListener: Consumer<WindowInsets> = Consumer { insets -> - // when taskbar is visible, stableInsetBottom will include its height - bottomStableInsets = insets.stableInsetBottom - bottomCutoutInsets = insets.displayCutout?.safeInsetBottom ?: 0 - updateBottomSpacing() + + // With certain configuration changes (like light/dark changes), the nav bar will disappear + // for a bit, causing `bottomStableInsets` to be unstable for some time. Debounce the value + // for 500ms. + // All interactions with this object happen in the main thread. + private val delayedInsetSetter = object : Runnable, Consumer<WindowInsets> { + private var canceller: Runnable? = null + private var stableInsets = 0 + private var cutoutInsets = 0 + + override fun accept(insets: WindowInsets) { + // when taskbar is visible, stableInsetBottom will include its height + stableInsets = insets.stableInsetBottom + cutoutInsets = insets.displayCutout?.safeInsetBottom ?: 0 + canceller?.run() + canceller = delayableExecutor.executeDelayed(this, INSET_DEBOUNCE_MILLIS) + } + + override fun run() { + bottomStableInsets = stableInsets + bottomCutoutInsets = cutoutInsets + updateBottomSpacing() + } } override fun onInit() { @@ -77,7 +102,7 @@ class NotificationsQSContainerController @Inject constructor( public override fun onViewAttached() { updateResources() overviewProxyService.addCallback(taskbarVisibilityListener) - mView.setInsetsChangedListener(windowInsetsListener) + mView.setInsetsChangedListener(delayedInsetSetter) mView.setQSFragmentAttachedListener { qs: QS -> qs.setContainerController(this) } mView.setConfigurationChangedListener { updateResources() } } 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 942aab58763e..78edc07c8544 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 @@ public abstract class PanelViewController { 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 @@ public abstract class PanelViewController { return true; } - @Classifier.InteractionType int interactionType = vel > 0 + @Classifier.InteractionType int interactionType = y - mInitialTouchY > 0 ? QUICK_SETTINGS : ( mKeyguardStateController.canDismissLockScreen() ? UNLOCK : BOUNCER_UNLOCK); @@ -796,6 +796,7 @@ public abstract class PanelViewController { } mExpandedFraction = Math.min(1f, maxPanelHeight == 0 ? 0 : mExpandedHeight / maxPanelHeight); + mAmbientState.setExpansionFraction(mExpandedFraction); onHeightUpdated(mExpandedHeight); updatePanelExpansionAndVisibility(); }); 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 0059c1b3642c..d7abf7430cac 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 @@ public class PhoneStatusBarPolicy } 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 419661b766d6..029a7a5fcdd5 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.annotations.VisibleForTesting; 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 @@ public class ScrimController implements ViewTreeObserver.OnPreDrawListener, Dump 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 @@ public class ScrimController implements ViewTreeObserver.OnPreDrawListener, Dump * 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 @@ public class ScrimController implements ViewTreeObserver.OnPreDrawListener, Dump } 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 @@ public class ScrimController implements ViewTreeObserver.OnPreDrawListener, Dump 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 637e4bee8948..6fe92fafc075 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 @@ class StatusBarNotificationActivityStarter implements NotificationActivityStarte 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 @@ class StatusBarNotificationActivityStarter implements NotificationActivityStarte 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 2c84219dbfd0..8194957c52fc 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_NOTIFICATION_ICONS; 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.statusbar.policy.KeyguardStateController; 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 @@ public class CollapsedStatusBarFragment extends Fragment implements CommandQueue } }; private OperatorNameViewController mOperatorNameViewController; + private StatusBarSystemEventAnimator mSystemEventAnimator; @SuppressLint("ValidFragment") public CollapsedStatusBarFragment( @@ -210,18 +210,31 @@ public class CollapsedStatusBarFragment extends Fragment implements CommandQueue 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 @@ public class CollapsedStatusBarFragment extends Fragment implements CommandQueue 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 @@ public class CollapsedStatusBarFragment extends Fragment implements CommandQueue mCommandQueue.removeCallback(this); mStatusBarStateController.removeCallback(this); mOngoingCallController.removeCallback(mOngoingCallListener); + mAnimationScheduler.removeCallback(this); mSecureSettings.unregisterContentObserver(mVolumeSettingObserver); } @@ -265,7 +280,6 @@ public class CollapsedStatusBarFragment extends Fragment implements CommandQueue public void onDestroyView() { super.onDestroyView(); mStatusBarIconController.removeIconGroup(mDarkIconManager); - mAnimationScheduler.removeCallback(this); if (mNetworkController.hasEmergencyCryptKeeperText()) { mNetworkController.removeCallback(mSignalCallback); } @@ -576,35 +590,16 @@ public class CollapsedStatusBarFragment extends Fragment implements CommandQueue 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); - } - } - - @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); - } + public Animator onSystemEventAnimationBegin() { + return mSystemEventAnimator.onSystemEventAnimationBegin(); } + @Nullable @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 000000000000..f530ec83aec5 --- /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/phone/userswitcher/StatusBarUserSwitcherController.kt b/packages/SystemUI/src/com/android/systemui/statusbar/phone/userswitcher/StatusBarUserSwitcherController.kt index 909261f0eb7e..62549a70897b 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/userswitcher/StatusBarUserSwitcherController.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/userswitcher/StatusBarUserSwitcherController.kt @@ -17,6 +17,7 @@ package com.android.systemui.statusbar.phone.userswitcher import android.content.Intent +import android.os.UserHandle import android.view.View import com.android.systemui.animation.ActivityLaunchAnimator import com.android.systemui.flags.FeatureFlags @@ -67,7 +68,7 @@ class StatusBarUserSwitcherControllerImpl @Inject constructor( activityStarter.startActivity(intent, true /* dismissShade */, ActivityLaunchAnimator.Controller.fromView(view, null), - true /* showOverlockscreenwhenlocked */) + true /* showOverlockscreenwhenlocked */, UserHandle.SYSTEM) } else { userSwitcherDialogController.showDialog(view) } 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 48949f92413d..4d6d05f2b628 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.Animator; 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.Dependency; 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 @@ public class RemoteInputView extends LinearLayout implements View.OnClickListene 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 @@ public class RemoteInputView extends LinearLayout implements View.OnClickListene // 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 @@ public class RemoteInputView extends LinearLayout implements View.OnClickListene 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 class RemoteInputView extends LinearLayout implements View.OnClickListene } 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 @@ public class RemoteInputView extends LinearLayout implements View.OnClickListene 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 class RemoteInputView extends LinearLayout implements View.OnClickListene } } + + 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 ef0a5b4235c7..f8451017b367 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.R 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 @@ interface RemoteInputViewController { 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 @@ interface RemoteInputViewController { /** 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 @@ interface RemoteInputViewController { /** 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 @@ class RemoteInputViewControllerImpl @Inject constructor( 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 @@ class RemoteInputViewControllerImpl @Inject constructor( 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 @@ class RemoteInputViewControllerImpl @Inject constructor( 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 @@ class RemoteInputViewControllerImpl @Inject constructor( 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 @@ class RemoteInputViewControllerImpl @Inject constructor( * @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 @@ class RemoteInputViewControllerImpl @Inject constructor( 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 @@ class RemoteInputViewControllerImpl @Inject constructor( 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 c0d7925cf2bb..9e9b74616d29 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.content.IntentFilter 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 @@ class UserSwitcherActivity @Inject constructor( } 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 @@ class UserSwitcherActivity @Inject constructor( 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 @@ class UserSwitcherActivity @Inject constructor( } } - 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 000000000000..c0538c110426 --- /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 000000000000..6266bf146f5b --- /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/ScreenDecorationsTest.java b/packages/SystemUI/tests/src/com/android/systemui/ScreenDecorationsTest.java index 70f325158624..ec92adb0f48c 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/ScreenDecorationsTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/ScreenDecorationsTest.java @@ -48,7 +48,6 @@ import android.content.res.Configuration; import android.content.res.TypedArray; import android.graphics.Insets; import android.graphics.PixelFormat; -import android.graphics.Point; import android.graphics.Rect; import android.graphics.drawable.VectorDrawable; import android.hardware.display.DisplayManager; @@ -58,6 +57,7 @@ import android.testing.AndroidTestingRunner; import android.testing.TestableLooper; import android.testing.TestableLooper.RunWithLooper; import android.util.RotationUtils; +import android.util.Size; import android.view.Display; import android.view.DisplayCutout; import android.view.View; @@ -73,6 +73,7 @@ import com.android.systemui.decor.DecorProvider; import com.android.systemui.decor.OverlayWindow; import com.android.systemui.decor.PrivacyDotCornerDecorProviderImpl; import com.android.systemui.decor.PrivacyDotDecorProviderFactory; +import com.android.systemui.decor.RoundedCornerResDelegate; import com.android.systemui.settings.UserTracker; import com.android.systemui.statusbar.events.PrivacyDotViewController; import com.android.systemui.tuner.TunerService; @@ -95,8 +96,6 @@ import java.util.ArrayList; @SmallTest public class ScreenDecorationsTest extends SysuiTestCase { - private static final Rect ZERO_RECT = new Rect(); - private ScreenDecorations mScreenDecorations; private WindowManager mWindowManager; private DisplayManager mDisplayManager; @@ -424,7 +423,7 @@ public class ScreenDecorationsTest extends SysuiTestCase { @Test public void testRoundingRadius_NoCutout() { - final Point testRadiusPoint = new Point(1, 1); + final Size testRadiusPoint = new Size(1, 1); setupResources(1 /* radius */, 1 /* radiusTop */, 1 /* radiusBottom */, 0 /* roundedPadding */, false /* multipleRadius */, false /* fillCutout */, true /* privacyDot */); @@ -433,9 +432,9 @@ public class ScreenDecorationsTest extends SysuiTestCase { mScreenDecorations.start(); // Size of corner view should same as rounded_corner_radius{_top|_bottom} - assertThat(mScreenDecorations.mRoundedDefault).isEqualTo(testRadiusPoint); - assertThat(mScreenDecorations.mRoundedDefaultTop).isEqualTo(testRadiusPoint); - assertThat(mScreenDecorations.mRoundedDefaultBottom).isEqualTo(testRadiusPoint); + final RoundedCornerResDelegate resDelegate = mScreenDecorations.mRoundedCornerResDelegate; + assertThat(resDelegate.getTopRoundedSize()).isEqualTo(testRadiusPoint); + assertThat(resDelegate.getBottomRoundedSize()).isEqualTo(testRadiusPoint); } @Test @@ -454,17 +453,17 @@ public class ScreenDecorationsTest extends SysuiTestCase { View rightRoundedCorner = mScreenDecorations.mOverlays[BOUNDS_POSITION_TOP].getRootView() .findViewById(R.id.right); verify(mScreenDecorations, atLeastOnce()) - .setSize(leftRoundedCorner, new Point(testTopRadius, testTopRadius)); + .setSize(leftRoundedCorner, new Size(testTopRadius, testTopRadius)); verify(mScreenDecorations, atLeastOnce()) - .setSize(rightRoundedCorner, new Point(testTopRadius, testTopRadius)); + .setSize(rightRoundedCorner, new Size(testTopRadius, testTopRadius)); leftRoundedCorner = mScreenDecorations.mOverlays[BOUNDS_POSITION_BOTTOM].getRootView() .findViewById(R.id.left); rightRoundedCorner = mScreenDecorations.mOverlays[BOUNDS_POSITION_BOTTOM].getRootView() .findViewById(R.id.right); verify(mScreenDecorations, atLeastOnce()) - .setSize(leftRoundedCorner, new Point(testBottomRadius, testBottomRadius)); + .setSize(leftRoundedCorner, new Size(testBottomRadius, testBottomRadius)); verify(mScreenDecorations, atLeastOnce()) - .setSize(rightRoundedCorner, new Point(testBottomRadius, testBottomRadius)); + .setSize(rightRoundedCorner, new Size(testBottomRadius, testBottomRadius)); } @Test @@ -480,8 +479,8 @@ public class ScreenDecorationsTest extends SysuiTestCase { .when(mScreenDecorations).getCutout(); mScreenDecorations.start(); - final Point topRadius = new Point(testTopRadius, testTopRadius); - final Point bottomRadius = new Point(testBottomRadius, testBottomRadius); + final Size topRadius = new Size(testTopRadius, testTopRadius); + final Size bottomRadius = new Size(testBottomRadius, testBottomRadius); View leftRoundedCorner = mScreenDecorations.mOverlays[BOUNDS_POSITION_LEFT].getRootView() .findViewById(R.id.left); boolean isTop = mScreenDecorations.isTopRoundedCorner(BOUNDS_POSITION_LEFT, R.id.left); @@ -510,7 +509,7 @@ public class ScreenDecorationsTest extends SysuiTestCase { @Test public void testRoundingMultipleRadius_NoCutout_NoPrivacyDot() { final VectorDrawable d = (VectorDrawable) mContext.getDrawable(R.drawable.rounded); - final Point multipleRadiusSize = new Point(d.getIntrinsicWidth(), d.getIntrinsicHeight()); + final Size multipleRadiusSize = new Size(d.getIntrinsicWidth(), d.getIntrinsicHeight()); setupResources(9999 /* radius */, 0 /* radiusTop */, 0 /* radiusBottom */, 9999 /* roundedPadding */, true /* multipleRadius */, false /* fillCutout */, false /* privacyDot */); @@ -536,15 +535,15 @@ public class ScreenDecorationsTest extends SysuiTestCase { verify(mDotViewController, never()).initialize(any(), any(), any(), any()); // Size of corner view should exactly match max(width, height) of R.drawable.rounded - assertThat(mScreenDecorations.mRoundedDefault).isEqualTo(multipleRadiusSize); - assertThat(mScreenDecorations.mRoundedDefaultTop).isEqualTo(multipleRadiusSize); - assertThat(mScreenDecorations.mRoundedDefaultBottom).isEqualTo(multipleRadiusSize); + final RoundedCornerResDelegate resDelegate = mScreenDecorations.mRoundedCornerResDelegate; + assertThat(resDelegate.getTopRoundedSize()).isEqualTo(multipleRadiusSize); + assertThat(resDelegate.getBottomRoundedSize()).isEqualTo(multipleRadiusSize); } @Test public void testRoundingMultipleRadius_NoCutout_PrivacyDot() { final VectorDrawable d = (VectorDrawable) mContext.getDrawable(R.drawable.rounded); - final Point multipleRadiusSize = new Point(d.getIntrinsicWidth(), d.getIntrinsicHeight()); + final Size multipleRadiusSize = new Size(d.getIntrinsicWidth(), d.getIntrinsicHeight()); setupResources(9999 /* radius */, 0 /* radiusTop */, 0 /* radiusBottom */, 9999 /* roundedPadding */, true /* multipleRadius */, false /* fillCutout */, true /* privacyDot */); @@ -571,9 +570,9 @@ public class ScreenDecorationsTest extends SysuiTestCase { isA(View.class), isA(View.class), isA(View.class), isA(View.class)); // Size of corner view should exactly match max(width, height) of R.drawable.rounded - assertThat(mScreenDecorations.mRoundedDefault).isEqualTo(multipleRadiusSize); - assertThat(mScreenDecorations.mRoundedDefaultTop).isEqualTo(multipleRadiusSize); - assertThat(mScreenDecorations.mRoundedDefaultBottom).isEqualTo(multipleRadiusSize); + final RoundedCornerResDelegate resDelegate = mScreenDecorations.mRoundedCornerResDelegate; + assertThat(resDelegate.getTopRoundedSize()).isEqualTo(multipleRadiusSize); + assertThat(resDelegate.getBottomRoundedSize()).isEqualTo(multipleRadiusSize); } @Test @@ -944,12 +943,15 @@ public class ScreenDecorationsTest extends SysuiTestCase { false /* fillCutout */, true /* privacyDot */); mScreenDecorations.start(); - assertEquals(mScreenDecorations.mRoundedDefault, new Point(20, 20)); + final RoundedCornerResDelegate resDelegate = mScreenDecorations.mRoundedCornerResDelegate; + assertEquals(resDelegate.getTopRoundedSize(), new Size(20, 20)); + assertEquals(resDelegate.getBottomRoundedSize(), new Size(20, 20)); when(mContext.getResources().getDimensionPixelSize( com.android.internal.R.dimen.rounded_corner_radius)).thenReturn(5); mScreenDecorations.onConfigurationChanged(null); - assertEquals(mScreenDecorations.mRoundedDefault, new Point(5, 5)); + assertEquals(resDelegate.getTopRoundedSize(), new Size(5, 5)); + assertEquals(resDelegate.getBottomRoundedSize(), new Size(5, 5)); } @Test @@ -959,9 +961,9 @@ public class ScreenDecorationsTest extends SysuiTestCase { false /* fillCutout */, true /* privacyDot */); mScreenDecorations.start(); - assertEquals(new Point(0, 0), mScreenDecorations.mRoundedDefault); - assertEquals(new Point(10, 10), mScreenDecorations.mRoundedDefaultTop); - assertEquals(new Point(0, 0), mScreenDecorations.mRoundedDefaultBottom); + final RoundedCornerResDelegate resDelegate = mScreenDecorations.mRoundedCornerResDelegate; + assertEquals(new Size(10, 10), resDelegate.getTopRoundedSize()); + assertEquals(new Size(0, 0), resDelegate.getBottomRoundedSize()); } @Test @@ -971,9 +973,9 @@ public class ScreenDecorationsTest extends SysuiTestCase { false /* fillCutout */, true /* privacyDot */); mScreenDecorations.start(); - assertEquals(new Point(0, 0), mScreenDecorations.mRoundedDefault); - assertEquals(new Point(0, 0), mScreenDecorations.mRoundedDefaultTop); - assertEquals(new Point(20, 20), mScreenDecorations.mRoundedDefaultBottom); + final RoundedCornerResDelegate resDelegate = mScreenDecorations.mRoundedCornerResDelegate; + assertEquals(new Size(0, 0), resDelegate.getTopRoundedSize()); + assertEquals(new Size(20, 20), resDelegate.getBottomRoundedSize()); } @Test diff --git a/packages/SystemUI/tests/src/com/android/systemui/SysuiTestCase.java b/packages/SystemUI/tests/src/com/android/systemui/SysuiTestCase.java index 7a0db1fd975c..8c7927782d2d 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 @@ public abstract class SysuiTestCase { } } + /** 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 a49c4d76445b..ee150ca9db1b 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/accessibility/WindowMagnificationControllerTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/accessibility/WindowMagnificationControllerTest.java @@ -80,6 +80,7 @@ import com.android.systemui.utils.os.FakeHandler; import org.junit.After; import org.junit.Before; +import org.junit.Ignore; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.Answers; @@ -172,11 +173,10 @@ public class WindowMagnificationControllerTest extends SysuiTestCase { @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 +184,16 @@ public class WindowMagnificationControllerTest extends SysuiTestCase { } @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, @@ -293,6 +303,7 @@ public class WindowMagnificationControllerTest extends SysuiTestCase { verify(mSfVsyncFrameProvider, atLeastOnce()).postFrameCallback(any()); } + @Ignore("b/224717753") @Test public void moveWindowMagnifierToPositionWithAnimation_expectedValuesAndInvokeCallback() throws InterruptedException { @@ -327,6 +338,7 @@ public class WindowMagnificationControllerTest extends SysuiTestCase { assertEquals(mWindowMagnificationController.getCenterY(), targetCenterY, 0); } + @Ignore("b/224717753") @Test public void moveWindowMagnifierToPositionMultipleTimes_expectedValuesAndInvokeCallback() throws InterruptedException { 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 ec2c1de49b4c..a95da6295350 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 @@ class AuthRippleControllerTest : SysuiTestCase() { } @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 @@ class AuthRippleControllerTest : SysuiTestCase() { } @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 @@ class AuthRippleControllerTest : SysuiTestCase() { // 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 ef82c3ec3322..fd49766dafef 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.Mockito.verify 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 @@ class UdfpsControllerOverlayTest : SysuiTestCase() { 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 @@ class UdfpsControllerOverlayTest : SysuiTestCase() { 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 613931f1341f..406ed5c17b0c 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.ArgumentMatchers.eq; 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 @@ public class UdfpsControllerTest extends SysuiTestCase { // 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 @@ public class UdfpsControllerTest extends SysuiTestCase { @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 @@ public class UdfpsControllerTest extends SysuiTestCase { 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 @@ public class UdfpsControllerTest extends SysuiTestCase { 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 @@ public class UdfpsControllerTest extends SysuiTestCase { 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 @@ public class UdfpsControllerTest extends SysuiTestCase { (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 @@ public class UdfpsControllerTest extends SysuiTestCase { } @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 @@ public class UdfpsControllerTest extends SysuiTestCase { 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 @@ public class UdfpsControllerTest extends SysuiTestCase { @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 @@ public class UdfpsControllerTest extends SysuiTestCase { @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 @@ public class UdfpsControllerTest extends SysuiTestCase { 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 @@ public class UdfpsControllerTest extends SysuiTestCase { 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 @@ public class UdfpsControllerTest extends SysuiTestCase { // 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 @@ public class UdfpsControllerTest extends SysuiTestCase { // 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 @@ public class UdfpsControllerTest extends SysuiTestCase { @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 @@ public class UdfpsControllerTest extends SysuiTestCase { @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 @@ public class UdfpsControllerTest extends SysuiTestCase { @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 @@ public class UdfpsControllerTest extends SysuiTestCase { // 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 @@ public class UdfpsControllerTest extends SysuiTestCase { // 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/decor/RoundedCornerResDelegateTest.kt b/packages/SystemUI/tests/src/com/android/systemui/decor/RoundedCornerResDelegateTest.kt new file mode 100644 index 000000000000..b536bfdb944e --- /dev/null +++ b/packages/SystemUI/tests/src/com/android/systemui/decor/RoundedCornerResDelegateTest.kt @@ -0,0 +1,139 @@ +/* + * 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.decor + +import android.content.res.TypedArray +import android.graphics.drawable.VectorDrawable +import android.testing.AndroidTestingRunner +import android.testing.TestableResources +import android.util.Size +import androidx.test.filters.SmallTest +import com.android.systemui.R +import com.android.systemui.SysuiTestCase +import org.junit.Assert.assertEquals +import org.junit.Before +import org.junit.Test + +import org.junit.runner.RunWith +import org.mockito.Mock +import org.mockito.MockitoAnnotations + +@RunWith(AndroidTestingRunner::class) +@SmallTest +class RoundedCornerResDelegateTest : SysuiTestCase() { + + private lateinit var roundedCornerResDelegate: RoundedCornerResDelegate + @Mock private lateinit var mockTypedArray: TypedArray + + @Before + fun setUp() { + MockitoAnnotations.initMocks(this) + } + + @Test + fun testReloadAllAndDefaultRadius() { + mContext.orCreateTestableResources.addOverrides( + mockTypeArray = mockTypedArray, + radius = 3, + radiusTop = 0, + radiusBottom = 4, + multipleRadius = false) + + roundedCornerResDelegate = RoundedCornerResDelegate(mContext.resources, null) + + assertEquals(Size(3, 3), roundedCornerResDelegate.topRoundedSize) + assertEquals(Size(4, 4), roundedCornerResDelegate.bottomRoundedSize) + assertEquals(false, roundedCornerResDelegate.isMultipleRadius) + + mContext.orCreateTestableResources.addOverrides( + mockTypeArray = mockTypedArray, + radius = 5, + radiusTop = 6, + radiusBottom = 0) + + roundedCornerResDelegate.reloadAll("test") + + assertEquals(Size(6, 6), roundedCornerResDelegate.topRoundedSize) + assertEquals(Size(5, 5), roundedCornerResDelegate.bottomRoundedSize) + } + + @Test + fun testUpdateTuningSizeFactor() { + mContext.orCreateTestableResources.addOverrides( + mockTypeArray = mockTypedArray, + radiusTop = 0, + radiusBottom = 0, + multipleRadius = false) + + roundedCornerResDelegate = RoundedCornerResDelegate(mContext.resources, null) + + val factor = 5 + roundedCornerResDelegate.updateTuningSizeFactor(factor) + val length = (factor * mContext.resources.displayMetrics.density).toInt() + + assertEquals(Size(length, length), roundedCornerResDelegate.topRoundedSize) + assertEquals(Size(length, length), roundedCornerResDelegate.bottomRoundedSize) + } + + @Test + fun testReadDefaultRadiusWhen0() { + mContext.orCreateTestableResources.addOverrides( + mockTypeArray = mockTypedArray, + radius = 3, + radiusTop = 0, + radiusBottom = 0, + multipleRadius = false) + + roundedCornerResDelegate = RoundedCornerResDelegate(mContext.resources, null) + + assertEquals(Size(3, 3), roundedCornerResDelegate.topRoundedSize) + assertEquals(Size(3, 3), roundedCornerResDelegate.bottomRoundedSize) + } + + @Test + fun testReadMultipleRadius() { + val d = mContext.getDrawable(R.drawable.rounded) as VectorDrawable + val multipleRadiusSize = Size(d.intrinsicWidth, d.intrinsicHeight) + mContext.orCreateTestableResources.addOverrides( + mockTypeArray = mockTypedArray, + multipleRadius = true) + roundedCornerResDelegate = RoundedCornerResDelegate(mContext.resources, null) + assertEquals(multipleRadiusSize, roundedCornerResDelegate.topRoundedSize) + assertEquals(multipleRadiusSize, roundedCornerResDelegate.bottomRoundedSize) + } +} + +private fun TestableResources.addOverrides( + mockTypeArray: TypedArray, + radius: Int? = null, + radiusTop: Int? = null, + radiusBottom: Int? = null, + multipleRadius: Boolean? = null +) { + addOverride(com.android.internal.R.array.config_displayUniqueIdArray, arrayOf<String>()) + addOverride(com.android.internal.R.array.config_roundedCornerRadiusArray, mockTypeArray) + addOverride(com.android.internal.R.array.config_roundedCornerTopRadiusArray, mockTypeArray) + addOverride(com.android.internal.R.array.config_roundedCornerBottomRadiusArray, mockTypeArray) + addOverride(R.array.config_roundedCornerDrawableArray, mockTypeArray) + addOverride(R.array.config_roundedCornerTopDrawableArray, mockTypeArray) + addOverride(R.array.config_roundedCornerBottomDrawableArray, mockTypeArray) + addOverride(R.array.config_roundedCornerMultipleRadiusArray, mockTypeArray) + radius?.let { addOverride(com.android.internal.R.dimen.rounded_corner_radius, it) } + radiusTop?.let { addOverride(com.android.internal.R.dimen.rounded_corner_radius_top, it) } + radiusBottom?.let { addOverride(com.android.internal.R.dimen.rounded_corner_radius_bottom, it) } + multipleRadius?.let { addOverride(R.bool.config_roundedCornerMultipleRadius, it) } +}
\ No newline at end of file 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 badafa4cf5e5..f4b378e6c19c 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.DOZE_REQUEST_PULSE; 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 class DozeScreenBrightnessTest extends SysuiTestCase { 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 @@ public class DozeScreenBrightnessTest extends SysuiTestCase { 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 @@ public class DozeScreenBrightnessTest extends SysuiTestCase { 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 a32ff801e824..a6921b441f17 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.ArgumentCaptor; 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 @@ public class DreamOverlayStatusBarViewControllerTest extends SysuiTestCase { @Mock ZenModeController mZenModeController; + private final Executor mMainExecutor = Runnable::run; + DreamOverlayStatusBarViewController mController; @Before @@ -102,6 +106,7 @@ public class DreamOverlayStatusBarViewControllerTest extends SysuiTestCase { mController = new DreamOverlayStatusBarViewController( mView, mResources, + mMainExecutor, mConnectivityManager, mTouchSession, mAlarmManager, @@ -134,7 +139,8 @@ public class DreamOverlayStatusBarViewControllerTest extends SysuiTestCase { .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 @@ public class DreamOverlayStatusBarViewControllerTest extends SysuiTestCase { .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 @@ public class DreamOverlayStatusBarViewControllerTest extends SysuiTestCase { 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 @@ public class DreamOverlayStatusBarViewControllerTest extends SysuiTestCase { 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 @@ public class DreamOverlayStatusBarViewControllerTest extends SysuiTestCase { 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 @@ public class DreamOverlayStatusBarViewControllerTest extends SysuiTestCase { 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 @@ public class DreamOverlayStatusBarViewControllerTest extends SysuiTestCase { 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 @@ public class DreamOverlayStatusBarViewControllerTest extends SysuiTestCase { 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 @@ public class DreamOverlayStatusBarViewControllerTest extends SysuiTestCase { 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 @@ public class DreamOverlayStatusBarViewControllerTest extends SysuiTestCase { 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 @@ public class DreamOverlayStatusBarViewControllerTest extends SysuiTestCase { 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 @@ public class DreamOverlayStatusBarViewControllerTest extends SysuiTestCase { 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 @@ public class DreamOverlayStatusBarViewControllerTest extends SysuiTestCase { .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 b02c506be8be..86aa14d7a877 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.junit.runner.RunWith; 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 @@ public class DreamClockDateComplicationTest extends SysuiTestCase { @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 @@ public class DreamClockDateComplicationTest extends SysuiTestCase { 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 088b4d5136ff..314a30b2d14a 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.junit.runner.RunWith; 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 @@ public class DreamClockTimeComplicationTest extends SysuiTestCase { @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 @@ public class DreamClockTimeComplicationTest extends SysuiTestCase { 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/flags/FeatureFlagsDebugTest.kt b/packages/SystemUI/tests/src/com/android/systemui/flags/FeatureFlagsDebugTest.kt index 23a5b2b2c5b7..50b779cb6bf5 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/flags/FeatureFlagsDebugTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/flags/FeatureFlagsDebugTest.kt @@ -67,9 +67,14 @@ class FeatureFlagsDebugTest : SysuiTestCase() { private lateinit var mBroadcastReceiver: BroadcastReceiver private lateinit var mClearCacheAction: Consumer<Int> + private val teamfoodableFlagA = BooleanFlag(500, false, true) + private val teamfoodableFlagB = BooleanFlag(501, true, true) + @Before fun setup() { MockitoAnnotations.initMocks(this) + mFlagMap.put(teamfoodableFlagA.id, teamfoodableFlagA) + mFlagMap.put(teamfoodableFlagB.id, teamfoodableFlagB) mFeatureFlagsDebug = FeatureFlagsDebug( mFlagManager, mMockContext, @@ -77,7 +82,7 @@ class FeatureFlagsDebugTest : SysuiTestCase() { mSystemProperties, mResources, mDumpManager, - { mFlagMap }, + mFlagMap, mBarService ) verify(mFlagManager).onSettingsChangedAction = any() @@ -93,12 +98,50 @@ class FeatureFlagsDebugTest : SysuiTestCase() { @Test fun testReadBooleanFlag() { + // Remember that the TEAMFOOD flag is id#1 and has special behavior. whenever(mFlagManager.readFlagValue<Boolean>(eq(3), any())).thenReturn(true) whenever(mFlagManager.readFlagValue<Boolean>(eq(4), any())).thenReturn(false) - assertThat(mFeatureFlagsDebug.isEnabled(BooleanFlag(1, false))).isFalse() assertThat(mFeatureFlagsDebug.isEnabled(BooleanFlag(2, true))).isTrue() assertThat(mFeatureFlagsDebug.isEnabled(BooleanFlag(3, false))).isTrue() assertThat(mFeatureFlagsDebug.isEnabled(BooleanFlag(4, true))).isFalse() + assertThat(mFeatureFlagsDebug.isEnabled(BooleanFlag(5, false))).isFalse() + } + + @Test + fun testTeamFoodFlag_False() { + whenever(mFlagManager.readFlagValue<Boolean>(eq(1), any())).thenReturn(false) + assertThat(mFeatureFlagsDebug.isEnabled(teamfoodableFlagA)).isFalse() + assertThat(mFeatureFlagsDebug.isEnabled(teamfoodableFlagB)).isTrue() + + // Regular boolean flags should still test the same. + // Only our teamfoodableFlag should change. + testReadBooleanFlag() + } + + @Test + fun testTeamFoodFlag_True() { + whenever(mFlagManager.readFlagValue<Boolean>(eq(1), any())).thenReturn(true) + assertThat(mFeatureFlagsDebug.isEnabled(teamfoodableFlagA)).isTrue() + assertThat(mFeatureFlagsDebug.isEnabled(teamfoodableFlagB)).isTrue() + + // Regular boolean flags should still test the same. + // Only our teamfoodableFlag should change. + testReadBooleanFlag() + } + + @Test + fun testTeamFoodFlag_Overridden() { + whenever(mFlagManager.readFlagValue<Boolean>(eq(teamfoodableFlagA.id), any())) + .thenReturn(true) + whenever(mFlagManager.readFlagValue<Boolean>(eq(teamfoodableFlagB.id), any())) + .thenReturn(false) + whenever(mFlagManager.readFlagValue<Boolean>(eq(1), any())).thenReturn(true) + assertThat(mFeatureFlagsDebug.isEnabled(teamfoodableFlagA)).isTrue() + assertThat(mFeatureFlagsDebug.isEnabled(teamfoodableFlagB)).isFalse() + + // Regular boolean flags should still test the same. + // Only our teamfoodableFlag should change. + testReadBooleanFlag() } @Test 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 dcbe0ab96dac..daf81bdc6e82 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.junit.runner.RunWith 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 @@ class MediaCarouselControllerTest : SysuiTestCase() { @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 cb68d81287df..90eff1ae9804 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 @@ public class MediaControlPanelTest : SysuiTestCase() { @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 @@ public class MediaControlPanelTest : SysuiTestCase() { 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 @@ public class MediaControlPanelTest : SysuiTestCase() { device = device, active = true, resumeAction = null) - - whenever(mediaFlags.areMediaSessionActionsEnabled()).thenReturn(false) - whenever(mediaFlags.useMediaSessionLayout()).thenReturn(false) } /** @@ -295,9 +291,6 @@ public class MediaControlPanelTest : SysuiTestCase() { @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 @@ public class MediaControlPanelTest : SysuiTestCase() { @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 @@ public class MediaControlPanelTest : SysuiTestCase() { @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 925ae30e8773..066f49a16f19 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.plugins.ActivityStarter 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 @@ class MediaDataManagerTest : SysuiTestCase() { 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 @@ class MediaDataManagerTest : SysuiTestCase() { @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 @@ class MediaDataManagerTest : SysuiTestCase() { @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 @@ class MediaDataManagerTest : SysuiTestCase() { @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 @@ class MediaDataManagerTest : SysuiTestCase() { @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 8e201b5a3e87..203eb47165e0 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 @@ class MediaHierarchyManagerTest : SysuiTestCase() { } @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/MediaViewControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/media/MediaViewControllerTest.kt new file mode 100644 index 000000000000..b7d5ba170e6d --- /dev/null +++ b/packages/SystemUI/tests/src/com/android/systemui/media/MediaViewControllerTest.kt @@ -0,0 +1,55 @@ +package com.android.systemui.media + +import android.testing.AndroidTestingRunner +import android.testing.TestableLooper +import android.view.View +import androidx.test.filters.SmallTest +import com.android.systemui.SysuiTestCase +import com.android.systemui.util.animation.MeasurementInput +import com.android.systemui.util.animation.TransitionLayout +import com.android.systemui.util.animation.TransitionViewState +import junit.framework.Assert.assertTrue +import org.junit.Before +import org.junit.Test +import org.junit.runner.RunWith + +/** + * Tests for {@link MediaViewController}. + */ +@SmallTest +@RunWith(AndroidTestingRunner::class) +@TestableLooper.RunWithLooper +class MediaViewControllerTest : SysuiTestCase() { + private val configurationController = + com.android.systemui.statusbar.phone.ConfigurationControllerImpl(context) + private val mediaHostStatesManager = MediaHostStatesManager() + private val mediaViewController = + MediaViewController(context, configurationController, mediaHostStatesManager) + private val mediaHostStateHolder = MediaHost.MediaHostStateHolder() + private var transitionLayout = TransitionLayout(context, /* attrs */ null, /* defStyleAttr */ 0) + + @Before + fun setUp() { + mediaViewController.attach(transitionLayout, MediaViewController.TYPE.PLAYER) + } + + @Test + fun testObtainViewState_applySquishFraction_toTransitionViewState_height() { + transitionLayout.measureState = TransitionViewState().apply { + this.height = 100 + } + mediaHostStateHolder.expansion = 1f + val widthMeasureSpec = View.MeasureSpec.makeMeasureSpec(100, View.MeasureSpec.EXACTLY) + val heightMeasureSpec = View.MeasureSpec.makeMeasureSpec(100, View.MeasureSpec.EXACTLY) + mediaHostStateHolder.measurementInput = + MeasurementInput(widthMeasureSpec, heightMeasureSpec) + + // Test no squish + mediaHostStateHolder.squishFraction = 1f + assertTrue(mediaViewController.obtainViewState(mediaHostStateHolder)!!.height == 100) + + // Test half squish + mediaHostStateHolder.squishFraction = 0.5f + assertTrue(mediaViewController.obtainViewState(mediaHostStateHolder)!!.height == 50) + } +}
\ No newline at end of file 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 ccce5778c150..b9a69bb8641a 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 @@ class MediaTttChipControllerCommonTest : SysuiTestCase() { 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 @@ class MediaTttChipControllerCommonTest : SysuiTestCase() { } @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 @@ class MediaTttChipControllerCommonTest : SysuiTestCase() { } @Test - fun displayChip_hasAppIconDrawable_iconIsDrawable() { + fun setIcon_hasAppIconDrawable_iconIsDrawable() { controllerCommon.displayChip(getState()) val chipView = getChipView() @@ -212,7 +237,29 @@ class MediaTttChipControllerCommonTest : SysuiTestCase() { } @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 @@ class MediaTttChipControllerCommonTest : SysuiTestCase() { } @Test - fun displayChip_hasAppName_iconContentDescriptionIsAppNameOverride() { + fun setIcon_hasAppName_iconContentDescriptionIsAppNameOverride() { controllerCommon.displayChip(getState()) val chipView = getChipView() @@ -233,6 +280,21 @@ class MediaTttChipControllerCommonTest : SysuiTestCase() { } @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 @@ class MediaTttChipControllerCommonTest : SysuiTestCase() { override fun updateChipView(chipInfo: ChipInfo, currentChipView: ViewGroup) { } + + override fun getIconSize(isAppIcon: Boolean): Int? = ICON_SIZE } inner class ChipInfo : ChipInfoCommon { @@ -307,3 +371,4 @@ class MediaTttChipControllerCommonTest : SysuiTestCase() { 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 355d3fe4b8d1..067607f9b8ae 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 @@ class MediaTttChipControllerReceiverTest : SysuiTestCase() { 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/navigationbar/NavigationBarTest.java b/packages/SystemUI/tests/src/com/android/systemui/navigationbar/NavigationBarTest.java index eb1e1a2e3d04..a0aa267e850e 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/navigationbar/NavigationBarTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/navigationbar/NavigationBarTest.java @@ -91,10 +91,10 @@ import com.android.systemui.statusbar.CommandQueue; import com.android.systemui.statusbar.NotificationRemoteInputManager; import com.android.systemui.statusbar.NotificationShadeDepthController; import com.android.systemui.statusbar.phone.AutoHideController; +import com.android.systemui.statusbar.phone.CentralSurfaces; import com.android.systemui.statusbar.phone.LightBarController; import com.android.systemui.statusbar.phone.NotificationShadeWindowView; import com.android.systemui.statusbar.phone.ShadeController; -import com.android.systemui.statusbar.phone.CentralSurfaces; import com.android.systemui.statusbar.policy.DeviceProvisionedController; import com.android.systemui.statusbar.policy.KeyguardStateController; import com.android.systemui.utils.leaks.LeakCheckedTest; @@ -387,14 +387,14 @@ public class NavigationBarTest extends SysuiTestCase { DeviceProvisionedController deviceProvisionedController = mock(DeviceProvisionedController.class); when(deviceProvisionedController.isDeviceProvisioned()).thenReturn(true); - NavigationBar.Factory factory = new NavigationBar.Factory( + return spy(new NavigationBar(context, + mWindowManager, () -> mAssistManager, mock(AccessibilityManager.class), deviceProvisionedController, new MetricsLogger(), mOverviewProxyService, mNavigationModeController, - mock(AccessibilityButtonModeObserver.class), mStatusBarStateController, mMockSysUiState, mBroadcastDispatcher, @@ -415,8 +415,7 @@ public class NavigationBarTest extends SysuiTestCase { mAutoHideControllerFactory, Optional.of(mTelecomManager), mInputMethodManager, - Optional.of(mock(BackAnimation.class))); - return spy(factory.create(context)); + Optional.of(mock(BackAnimation.class)))); } private void processAllMessages() { 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 350822691121..38b448fb362c 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 @@ package com.android.systemui.privacy 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 @@ class PrivacyDialogControllerTest : SysuiTestCase() { } } + @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 @@ class PrivacyDialogControllerTest : SysuiTestCase() { 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/QRCodeScannerTileTest.java b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/QRCodeScannerTileTest.java index 8297850d21a1..b652aee0f6aa 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/QRCodeScannerTileTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/QRCodeScannerTileTest.java @@ -104,8 +104,6 @@ public class QRCodeScannerTileTest extends SysuiTestCase { assertEquals(state.label, mContext.getString(R.string.qr_code_scanner_title)); assertEquals(state.contentDescription, mContext.getString(R.string.qr_code_scanner_title)); assertEquals(state.icon, QSTileImpl.ResourceIcon.get(R.drawable.ic_qr_code_scanner)); - assertEquals(state.secondaryLabel, - mContext.getString(R.string.qr_code_scanner_description)); } @Test 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 d3bb241baad4..f306fd601136 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.android.systemui.qs.tiles.dialog.InternetDialogController.MAX_ 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.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; @@ -40,6 +46,7 @@ import java.util.List; @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 @@ public class InternetAdapterTest extends SysuiTestCase { @Rule public MockitoRule mRule = MockitoJUnit.rule(); + @Spy + private Context mSpyContext = mContext; @Mock private WifiEntry mInternetWifiEntry; @@ -74,6 +83,7 @@ public class InternetAdapterTest extends SysuiTestCase { 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 @@ public class InternetAdapterTest extends SysuiTestCase { } @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 a2959e2fb917..633a9c3a03d8 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 @@ public class InternetDialogControllerTest extends SysuiTestCase { } @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 3c1a73eb672e..a2a02cd939ef 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 static org.mockito.Mockito.when; 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 @@ public class KeyguardIndicationControllerTest extends SysuiTestCase { @Mock private DevicePolicyManager mDevicePolicyManager; @Mock + private DevicePolicyResourcesManager mDevicePolicyResourcesManager; + @Mock private ViewGroup mIndicationArea; @Mock private KeyguardStateController mKeyguardStateController; @@ -210,12 +213,14 @@ public class KeyguardIndicationControllerTest extends SysuiTestCase { .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 @@ public class KeyguardIndicationControllerTest extends SysuiTestCase { @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 64a0a2342a44..1d2a0ca3777a 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.row.NotificationTestHelper 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.anyBoolean 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 @@ class LockscreenShadeTransitionControllerTest : SysuiTestCase() { 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 @@ class LockscreenShadeTransitionControllerTest : SysuiTestCase() { 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 @@ class LockscreenShadeTransitionControllerTest : SysuiTestCase() { } @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 @@ class LockscreenShadeTransitionControllerTest : SysuiTestCase() { } 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 ca8529d5cb03..52bacd2360b3 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.notification.interruption.KeyguardNotifica 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 7fc5ece670d4..251ac7d250fe 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 android.testing.TestableLooper; 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.phone.KeyguardBypassController; 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 @@ public class NotificationEntryManagerInflationTest extends SysuiTestCase { .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 @@ public class NotificationEntryManagerInflationTest extends SysuiTestCase { 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 72f8f70058fc..1ecb09bc8514 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.text.TextUtils; 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.plugins.statusbar.StatusBarStateController; 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.phone.KeyguardBypassController; 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 @@ public class NotificationTestHelper { 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 bf16e0ab39c6..c9de60806b66 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 @@ public class NotificationStackScrollLayoutControllerTest extends SysuiTestCase { @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 @@ public class NotificationStackScrollLayoutControllerTest extends SysuiTestCase { 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 eafcc354fac4..7a92b96f40db 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 @@ public class NotificationStackScrollLayoutTest extends SysuiTestCase { @Mock private NotificationStackScrollLayoutController mStackScrollLayoutController; @Mock private UnlockedScreenOffAnimationController mUnlockedScreenOffAnimationController; @Mock private NotificationShelf mNotificationShelf; + @Mock private NotificationStackSizeCalculator mNotificationStackSizeCalculator; @Before @UiThreadTest @@ -138,7 +139,8 @@ public class NotificationStackScrollLayoutTest extends SysuiTestCase { // 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 @@ public class NotificationStackScrollLayoutTest extends SysuiTestCase { } @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 000000000000..d1848e38ca06 --- /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 4bac08ea536b..06b20380c0ab 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.CommandQueue; 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.ConversationNotificationManag 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 @@ public class NotificationPanelViewControllerTest extends SysuiTestCase { @Mock private NotificationShelfController mNotificationShelfController; @Mock - private NotificationGroupManagerLegacy mGroupManager; - @Mock private KeyguardStatusBarView mKeyguardStatusBar; @Mock private KeyguardUserSwitcherView mUserSwitcherView; @@ -200,10 +197,6 @@ public class NotificationPanelViewControllerTest extends SysuiTestCase { @Mock private DynamicPrivacyController mDynamicPrivacyController; @Mock - private ShadeController mShadeController; - @Mock - private NotificationLockscreenUserManager mNotificationLockscreenUserManager; - @Mock private NotificationEntryManager mNotificationEntryManager; @Mock private StatusBarTouchableRegionManager mStatusBarTouchableRegionManager; @@ -336,6 +329,8 @@ public class NotificationPanelViewControllerTest extends SysuiTestCase { 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 @@ public class NotificationPanelViewControllerTest extends SysuiTestCase { mFeatureFlags, coordinator, expansionHandler, mDynamicPrivacyController, mKeyguardBypassController, mFalsingManager, new FalsingCollectorFake(), - mNotificationLockscreenUserManager, mNotificationEntryManager, + mNotificationEntryManager, mKeyguardStateController, mStatusBarStateController, mStatusBarWindowStateController, @@ -484,7 +479,6 @@ public class NotificationPanelViewControllerTest extends SysuiTestCase { mKeyguardUserSwitcherComponentFactory, mKeyguardStatusBarViewComponentFactory, mLockscreenShadeTransitionController, - mGroupManager, mNotificationAreaController, mAuthController, mScrimController, @@ -516,7 +510,8 @@ public class NotificationPanelViewControllerTest extends SysuiTestCase { 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 83eabb667997..9e7b6c514ca3 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.View 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 @@ -19,6 +18,8 @@ import com.android.systemui.navigationbar.NavigationModeController import com.android.systemui.navigationbar.NavigationModeController.ModeChangedListener import com.android.systemui.recents.OverviewProxyService import com.android.systemui.recents.OverviewProxyService.OverviewProxyListener +import com.android.systemui.util.concurrency.FakeExecutor +import com.android.systemui.util.time.FakeSystemClock import com.google.common.truth.Truth.assertThat import org.junit.Before import org.junit.Test @@ -32,6 +33,7 @@ import org.mockito.Mockito.anyInt import org.mockito.Mockito.doNothing import org.mockito.Mockito.eq import org.mockito.Mockito.mock +import org.mockito.Mockito.never import org.mockito.Mockito.verify import org.mockito.MockitoAnnotations import java.util.function.Consumer @@ -72,6 +74,8 @@ class NotificationQSContainerControllerTest : SysuiTestCase() { private lateinit var navigationModeCallback: ModeChangedListener private lateinit var taskbarVisibilityCallback: OverviewProxyListener private lateinit var windowInsetsCallback: Consumer<WindowInsets> + private lateinit var delayableExecutor: FakeExecutor + private lateinit var fakeSystemClock: FakeSystemClock @Before fun setup() { @@ -79,11 +83,14 @@ class NotificationQSContainerControllerTest : SysuiTestCase() { mContext.ensureTestableResources() whenever(notificationsQSContainer.context).thenReturn(mContext) whenever(notificationsQSContainer.resources).thenReturn(mContext.resources) + fakeSystemClock = FakeSystemClock() + delayableExecutor = FakeExecutor(fakeSystemClock) controller = NotificationsQSContainerController( notificationsQSContainer, navigationModeController, overviewProxyService, - featureFlags + featureFlags, + delayableExecutor ) overrideResource(R.dimen.split_shade_notifications_scrim_margin_bottom, SCRIM_MARGIN) @@ -104,10 +111,6 @@ class NotificationQSContainerControllerTest : SysuiTestCase() { windowInsetsCallback = windowInsetsCallbackCaptor.value } - private fun overrideResource(@AnyRes id: Int, value: Any) { - mContext.orCreateTestableResources.addOverride(id, value) - } - @Test fun testTaskbarVisibleInSplitShade() { enableSplitShade() @@ -495,13 +498,32 @@ class NotificationQSContainerControllerTest : SysuiTestCase() { container.addView(newViewWithId(1)) container.addView(newViewWithId(View.NO_ID)) val controller = NotificationsQSContainerController(container, navigationModeController, - overviewProxyService, featureFlags) + overviewProxyService, featureFlags, delayableExecutor) controller.updateResources() assertThat(container.getChildAt(0).id).isEqualTo(1) assertThat(container.getChildAt(1).id).isNotEqualTo(View.NO_ID) } + @Test + fun testWindowInsetDebounce() { + disableSplitShade() + useNewFooter(true) + + given(taskbarVisible = false, + navigationMode = GESTURES_NAVIGATION, + insets = emptyInsets(), + applyImmediately = false) + fakeSystemClock.advanceTime(INSET_DEBOUNCE_MILLIS / 2) + windowInsetsCallback.accept(windowInsets().withStableBottom()) + + delayableExecutor.advanceClockToLast() + delayableExecutor.runAllReady() + + verify(notificationsQSContainer, never()).setQSContainerPaddingBottom(0) + verify(notificationsQSContainer).setQSContainerPaddingBottom(STABLE_INSET_BOTTOM) + } + private fun disableSplitShade() { setSplitShadeEnabled(false) } @@ -518,12 +540,17 @@ class NotificationQSContainerControllerTest : SysuiTestCase() { private fun given( taskbarVisible: Boolean, navigationMode: Int, - insets: WindowInsets + insets: WindowInsets, + applyImmediately: Boolean = true ) { Mockito.clearInvocations(notificationsQSContainer) taskbarVisibilityCallback.onTaskbarStatusUpdated(taskbarVisible, false) navigationModeCallback.onNavigationModeChanged(navigationMode) windowInsetsCallback.accept(insets) + if (applyImmediately) { + delayableExecutor.advanceClockToLast() + delayableExecutor.runAllReady() + } } fun then( 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 0b25467d20d8..786a8586ea39 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 @@ public class ScrimControllerTest extends SysuiTestCase { 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 d48ce8c6803e..fa867e2796f7 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 @@ public class StatusBarNotificationActivityStarterTest extends SysuiTestCase { 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 20a3fdaa99a5..3a0a7c9d80fc 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 @@ public class RemoteInputViewTest extends SysuiTestCase { 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 @@ public class RemoteInputViewTest extends SysuiTestCase { 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 @@ public class RemoteInputViewTest extends SysuiTestCase { 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 @@ public class RemoteInputViewTest extends SysuiTestCase { 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 @@ public class RemoteInputViewTest extends SysuiTestCase { 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 000000000000..92afb038b321 --- /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 40821185b61a..38d74e4a73ce 100644 --- a/proto/src/camera.proto +++ b/proto/src/camera.proto @@ -66,5 +66,5 @@ message CameraStreamProto { // 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 3f712dd1492f..3801c2473c11 100644 --- a/proto/src/metrics_constants/metrics_constants.proto +++ b/proto/src/metrics_constants/metrics_constants.proto @@ -2260,10 +2260,12 @@ message MetricsEvent { 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 249ee16afaae..61e3da8aae51 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 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub @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 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub * * @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 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub /** * 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 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub /** * 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) { + mMainHandler.sendMessage(obtainMessage(AccessibilityManagerService::startInput, this, + startInputToken, inputContext, editorInfo, restarting)); + } + + private void startInput(IBinder startInputToken, IInputContext inputContext, EditorInfo editorInfo, boolean restarting) { - AccessibilityUserState userState; 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 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub * 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 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub * @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 fa32452f389e..ecc45eb743c6 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 @@ package com.android.server.accessibility.magnification; 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.BroadcastReceiver; 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 @@ public class FullScreenMagnificationController implements // 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 @@ public class FullScreenMagnificationController implements 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 @@ public class FullScreenMagnificationController implements 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 @@ public class FullScreenMagnificationController implements 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 @@ public class FullScreenMagnificationController implements 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 @@ public class FullScreenMagnificationController implements 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 3d8f5173d25a..a5c8837dd8f5 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 @@ public final class GesturesObserver implements GestureMatcher.StateChangeListene * 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 085c343ff631..23cded771cae 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 @@ class MagnificationGesturesObserver implements GesturesObserver.Listener { mDelayedEventQueue = null; mCallback.onGestureCompleted(gestureId, mLastDownEventTime, delayEventQueue, event); - recycleLastEvent(); + clear(); } @Override @@ -149,19 +149,18 @@ class MagnificationGesturesObserver implements GesturesObserver.Listener { 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 820be28387ae..9ff51eecba1d 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 @@ public class WindowMagnificationGestureHandler extends MagnificationGestureHandl } @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/accessibility/java/com/android/server/accessibility/magnification/WindowMagnificationManager.java b/services/accessibility/java/com/android/server/accessibility/magnification/WindowMagnificationManager.java index aeb1112ede5f..ca116e35eb56 100644 --- a/services/accessibility/java/com/android/server/accessibility/magnification/WindowMagnificationManager.java +++ b/services/accessibility/java/com/android/server/accessibility/magnification/WindowMagnificationManager.java @@ -108,6 +108,17 @@ public class WindowMagnificationManager implements private @interface ConnectionState { } + private static String connectionStateToString(@ConnectionState int state) { + switch (state) { + case CONNECTING: return "CONNECTING"; + case CONNECTED: return "CONNECTED"; + case DISCONNECTING: return "DISCONNECTING"; + case DISCONNECTED: return "DISCONNECTED"; + default: + return "UNKNOWN:" + state; + } + } + @ConnectionState private int mConnectionState = DISCONNECTED; @@ -205,7 +216,8 @@ public class WindowMagnificationManager implements */ public void setConnection(@Nullable IWindowMagnificationConnection connection) { if (DBG) { - Slog.d(TAG, "setConnection :" + connection + " ,mConnectionState=" + mConnectionState); + Slog.d(TAG, "setConnection :" + connection + ", mConnectionState=" + + connectionStateToString(mConnectionState)); } synchronized (mLock) { // Reset connectionWrapper. @@ -275,9 +287,8 @@ public class WindowMagnificationManager implements if ((connect && (mConnectionState == CONNECTED || mConnectionState == CONNECTING)) || (!connect && (mConnectionState == DISCONNECTED || mConnectionState == DISCONNECTING))) { - Slog.w(TAG, - "requestConnection duplicated request: connect=" + connect - + " ,mConnectionState=" + mConnectionState); + Slog.w(TAG, "requestConnection duplicated request: connect=" + connect + + ", mConnectionState=" + connectionStateToString(mConnectionState)); return false; } @@ -321,14 +332,14 @@ public class WindowMagnificationManager implements /** * Returns window magnification connection state. */ - public int getConnectionState() { - return mConnectionState; + public String getConnectionState() { + return connectionStateToString(mConnectionState); } private void setConnectionState(@ConnectionState int state) { if (DBG) { - Slog.d(TAG, "setConnectionState : state=" + state + " ,mConnectionState=" - + mConnectionState); + Slog.d(TAG, "setConnectionState : state=" + state + ", mConnectionState=" + + connectionStateToString(mConnectionState)); } mConnectionState = state; } @@ -1114,7 +1125,7 @@ public class WindowMagnificationManager implements if (mConnectionWrapper == null) { Slog.w(TAG, "enableWindowMagnificationInternal mConnectionWrapper is null. " - + "mConnectionState=" + mConnectionState); + + "mConnectionState=" + connectionStateToString(mConnectionState)); return false; } return mConnectionWrapper.enableWindowMagnification( diff --git a/services/api/current.txt b/services/api/current.txt index 5a2880223f6c..780fccfc2e4d 100644 --- a/services/api/current.txt +++ b/services/api/current.txt @@ -47,6 +47,9 @@ package com.android.server.am { 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/AutofillManagerServiceImpl.java b/services/autofill/java/com/android/server/autofill/AutofillManagerServiceImpl.java index 1cff3744687e..8c4db70c301d 100644 --- a/services/autofill/java/com/android/server/autofill/AutofillManagerServiceImpl.java +++ b/services/autofill/java/com/android/server/autofill/AutofillManagerServiceImpl.java @@ -16,6 +16,8 @@ package com.android.server.autofill; +import static android.service.autofill.FillEventHistory.Event.NO_SAVE_UI_REASON_NONE; +import static android.service.autofill.FillEventHistory.Event.UI_TYPE_INLINE; import static android.service.autofill.FillRequest.FLAG_MANUAL_REQUEST; import static android.view.autofill.AutofillManager.ACTION_START_SESSION; import static android.view.autofill.AutofillManager.FLAG_ADD_CLIENT_ENABLED; @@ -816,12 +818,13 @@ final class AutofillManagerServiceImpl /** * Updates the last fill response when a dataset is shown. */ - void logDatasetShown(int sessionId, @Nullable Bundle clientState) { + void logDatasetShown(int sessionId, @Nullable Bundle clientState, int presentationType) { synchronized (mLock) { if (isValidEventLocked("logDatasetShown", sessionId)) { mEventHistory.addEvent( new Event(Event.TYPE_DATASETS_SHOWN, null, clientState, null, null, null, - null, null, null, null, null)); + null, null, null, null, null, NO_SAVE_UI_REASON_NONE, + presentationType)); } } } @@ -858,9 +861,12 @@ final class AutofillManagerServiceImpl || mAugmentedAutofillEventHistory.getSessionId() != sessionId) { return; } + // Augmented Autofill only logs for inline now, so set UI_TYPE_INLINE here. + // Ideally should not hardcode here and should also log for menu presentation. mAugmentedAutofillEventHistory.addEvent( new Event(Event.TYPE_DATASETS_SHOWN, null, clientState, null, null, null, - null, null, null, null, null)); + null, null, null, null, null, NO_SAVE_UI_REASON_NONE, + UI_TYPE_INLINE)); } } diff --git a/services/autofill/java/com/android/server/autofill/Session.java b/services/autofill/java/com/android/server/autofill/Session.java index e0fa67f64c4c..54183c98204e 100644 --- a/services/autofill/java/com/android/server/autofill/Session.java +++ b/services/autofill/java/com/android/server/autofill/Session.java @@ -18,9 +18,12 @@ package com.android.server.autofill; 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.FillEventHistory.Event.UI_TYPE_DIALOG; +import static android.service.autofill.FillEventHistory.Event.UI_TYPE_INLINE; +import static android.service.autofill.FillEventHistory.Event.UI_TYPE_MENU; 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 +968,7 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState 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 +1014,8 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState 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 +3005,7 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState // 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); @@ -3290,7 +3293,7 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState synchronized (mLock) { final ViewState currentView = mViewStates.get(mCurrentViewId); currentView.setState(ViewState.STATE_FILL_DIALOG_SHOWN); - mService.logDatasetShown(id, mClientState); + mService.logDatasetShown(id, mClientState, UI_TYPE_DIALOG); } return; } @@ -3304,7 +3307,7 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState currentView.setState(ViewState.STATE_INLINE_SHOWN); //TODO(b/137800469): Fix it to log showed only when IME asks for inflation, // rather than here where framework sends back the response. - mService.logDatasetShown(id, mClientState); + mService.logDatasetShown(id, mClientState, UI_TYPE_INLINE); return; } } @@ -3314,7 +3317,9 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState mService.getServicePackageName(), mComponentName, targetLabel, targetIcon, this, id, mCompatMode); - mService.logDatasetShown(id, mClientState); + synchronized (mLock) { + mService.logDatasetShown(id, mClientState, UI_TYPE_MENU); + } synchronized (mLock) { if (mUiShownTime == 0) { diff --git a/services/backup/java/com/android/server/backup/UserBackupManagerService.java b/services/backup/java/com/android/server/backup/UserBackupManagerService.java index e10151dbd04b..1af35af9fc17 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.ServiceManager; 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 @@ public class UserBackupManagerService { 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 @@ public class UserBackupManagerService { mBackupPasswordManager = null; mPackageManagerBinder = null; mActivityManager = null; - mStorageManager = null; mBackupManagerBinder = null; mScheduledBackupEligibility = null; } @@ -560,7 +556,6 @@ public class UserBackupManagerService { 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 @@ public class UserBackupManagerService { } } - /** 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 7ee307e30dce..ec58e17148b3 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 @@ public class PerformAdbBackupTask extends FullBackupTask implements BackupRestor 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 116c7391b388..8e0e3959dd0e 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 @@ public class CloudSearchPerUserService extends @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 bf8b18ce3157..7a5fa628f645 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.Parcel; 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 @@ class AssociationRequestsProcessor { } } - 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 @@ class AssociationRequestsProcessor { } } - 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<>(); + boolean requestingPackageSignatureAllowlisted = false; + for (String signatureDigest : requestingPackageSignatureDigests) { + if (allowlistedSignatureDigestsForRequestingPackage.contains(signatureDigest)) { + requestingPackageSignatureAllowlisted = true; + break; + } + } - // 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(":", "")); + 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 sameOemPackageCerts; + 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 f32eebc2a31f..2a83a3c431ec 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 @@ import java.util.Map; * 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 @@ class CompanionApplicationController { 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 @@ class CompanionApplicationController { } 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 eaa99f74e24e..13a5a2829945 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 @@ public class CompanionDeviceManagerService extends SystemService { 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 f2a58b74a65a..a6bd48056e12 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 @@ import com.android.server.ServiceThread; 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 @@ class CompanionDeviceServiceConnector extends ServiceConnector.Impl<ICompanionDe 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 @@ class CompanionDeviceServiceConnector extends ServiceConnector.Impl<ICompanionDe 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 1ba198ae26b0..823743da7da6 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 @@ class BluetoothCompanionDeviceConnectionListener 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 be2b7f72bd4f..7c3a75f256f9 100644 --- a/services/core/java/com/android/server/MasterClearReceiver.java +++ b/services/core/java/com/android/server/MasterClearReceiver.java @@ -131,7 +131,7 @@ public class MasterClearReceiver extends BroadcastReceiver { 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 @@ public class MasterClearReceiver extends BroadcastReceiver { 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 186ff6215c9c..2015dc929a59 100644 --- a/services/core/java/com/android/server/NetworkTimeUpdateService.java +++ b/services/core/java/com/android/server/NetworkTimeUpdateService.java @@ -196,13 +196,15 @@ public class NetworkTimeUpdateService extends Binder { * 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 464af01a009a..d7504ceb9d4d 100644 --- a/services/core/java/com/android/server/NetworkTimeUpdateServiceShellCommand.java +++ b/services/core/java/com/android/server/NetworkTimeUpdateServiceShellCommand.java @@ -46,6 +46,7 @@ class NetworkTimeUpdateServiceShellCommand extends ShellCommand { */ 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 @@ class NetworkTimeUpdateServiceShellCommand extends ShellCommand { private int runSetServerConfig() { String hostname = null; + Integer port = null; Duration timeout = null; String opt; while ((opt = getNextArg()) != null) { @@ -95,6 +97,10 @@ class NetworkTimeUpdateServiceShellCommand extends ShellCommand { 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 @@ class NetworkTimeUpdateServiceShellCommand extends ShellCommand { } } } - mNetworkTimeUpdateService.setServerConfigForTests(hostname, timeout); + mNetworkTimeUpdateService.setServerConfigForTests(hostname, port, timeout); return 0; } @@ -120,8 +126,9 @@ class NetworkTimeUpdateServiceShellCommand extends ShellCommand { 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 7075ed34dfb4..a2cfe4928249 100644 --- a/services/core/java/com/android/server/StorageManagerService.java +++ b/services/core/java/com/android/server/StorageManagerService.java @@ -3129,220 +3129,6 @@ class StorageManagerService extends IStorageManager.Stub } } - @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 @@ class StorageManagerService extends IStorageManager.Stub } @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 569d4809a541..2dfe94729bb8 100644 --- a/services/core/java/com/android/server/UiModeManagerService.java +++ b/services/core/java/com/android/server/UiModeManagerService.java @@ -1302,7 +1302,7 @@ final class UiModeManagerService extends SystemService { 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 @@ final class UiModeManagerService extends SystemService { 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 @@ final class UiModeManagerService extends SystemService { 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 class UiModeManagerService extends SystemService { } 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 @@ final class UiModeManagerService extends SystemService { 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 @@ final class UiModeManagerService extends SystemService { 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 @@ final class UiModeManagerService extends SystemService { 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 7b8cce54c8a7..c1d8e7bf3dc0 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.NetworkStack; 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 @@ public class VpnManagerService extends IVpnManager.Stub { } /** + * 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 48e3264b2c11..b0ab5390724b 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 @@ public final class ActiveServices { @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 @@ public final class ActiveServices { 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/ActivityManagerConstants.java b/services/core/java/com/android/server/am/ActivityManagerConstants.java index c42666247e98..cc8c6fb6c23a 100644 --- a/services/core/java/com/android/server/am/ActivityManagerConstants.java +++ b/services/core/java/com/android/server/am/ActivityManagerConstants.java @@ -668,11 +668,11 @@ final class ActivityManagerConstants extends ContentObserver { "no_kill_cached_processes_post_boot_completed_duration_millis"; /** @see #mNoKillCachedProcessesUntilBootCompleted */ - private static final boolean DEFAULT_NO_KILL_CACHED_PROCESSES_UNTIL_BOOT_COMPLETED = false; + private static final boolean DEFAULT_NO_KILL_CACHED_PROCESSES_UNTIL_BOOT_COMPLETED = true; /** @see #mNoKillCachedProcessesPostBootCompletedDurationMillis */ private static final long - DEFAULT_NO_KILL_CACHED_PROCESSES_POST_BOOT_COMPLETED_DURATION_MILLIS = 0; + DEFAULT_NO_KILL_CACHED_PROCESSES_POST_BOOT_COMPLETED_DURATION_MILLIS = 600_000; /** * If true, do not kill excessive cached processes proactively, until user-0 is unlocked. diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java index 0735648c1069..36fdb9d40e8e 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.permission.PermissionManagerServiceInternal; 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 @@ public class ActivityManagerService extends IActivityManager.Stub 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 @@ public class ActivityManagerService extends IActivityManager.Stub 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 @@ public class ActivityManagerService extends IActivityManager.Stub } 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 @@ public class ActivityManagerService extends IActivityManager.Stub 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 @@ public class ActivityManagerService extends IActivityManager.Stub 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 @@ public class ActivityManagerService extends IActivityManager.Stub 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 class ActivityManagerService extends IActivityManager.Stub 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 @@ public class ActivityManagerService extends IActivityManager.Stub } 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 @@ public class ActivityManagerService extends IActivityManager.Stub } } + 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 @@ public class ActivityManagerService extends IActivityManager.Stub 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 @@ public class ActivityManagerService extends IActivityManager.Stub 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 @@ public class ActivityManagerService extends IActivityManager.Stub 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 d1cf0049d146..6f11b0001c7a 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.NonNull; 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 @@ final class AppBatteryExemptionTracker // 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 @@ final class AppBatteryExemptionTracker .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); + } + 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); } - pkg.addEvent(start, now, batteryUsage, stateTypeIndex); + } + } + + @VisibleForTesting + @Override + void reset() { + super.reset(); + synchronized (mLock) { + mUidPackageStates.clear(); } } @@ -116,6 +187,7 @@ final class AppBatteryExemptionTracker 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 7cd45fed1498..690051f47326 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.app.usage.UsageStatsManager.REASON_SUB_USAGE_USER_INTERACT 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 android.util.TimeUtils.formatTime; 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.Context; 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.Slog; 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.annotations.VisibleForTesting; 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 @@ final class AppBatteryTracker extends BaseAppStateTracker<AppBatteryPolicy> 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 @@ final class AppBatteryTracker extends BaseAppStateTracker<AppBatteryPolicy> 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 @@ final class AppBatteryTracker extends BaseAppStateTracker<AppBatteryPolicy> 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 @@ final class AppBatteryTracker extends BaseAppStateTracker<AppBatteryPolicy> 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 @@ final class AppBatteryTracker extends BaseAppStateTracker<AppBatteryPolicy> } 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 @@ final class AppBatteryTracker extends BaseAppStateTracker<AppBatteryPolicy> } 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 @@ final class AppBatteryTracker extends BaseAppStateTracker<AppBatteryPolicy> 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 @@ final class AppBatteryTracker extends BaseAppStateTracker<AppBatteryPolicy> /** * 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 @@ final class AppBatteryTracker extends BaseAppStateTracker<AppBatteryPolicy> /** * 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 @@ final class AppBatteryTracker extends BaseAppStateTracker<AppBatteryPolicy> 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 075402f10882..246725e03ba6 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 static com.android.server.am.BaseAppStateTracker.ONE_HOUR; 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.AppFGSTracker.PackageDurations; 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 @@ final class AppFGSTracker extends BaseAppStateDurationsTracker<AppFGSPolicy, Pac 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 @@ final class AppFGSTracker extends BaseAppStateDurationsTracker<AppFGSPolicy, Pac 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 @@ final class AppFGSTracker extends BaseAppStateDurationsTracker<AppFGSPolicy, Pac 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 @@ final class AppFGSTracker extends BaseAppStateDurationsTracker<AppFGSPolicy, Pac 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 @@ final class AppFGSTracker extends BaseAppStateDurationsTracker<AppFGSPolicy, Pac @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 @@ final class AppFGSTracker extends BaseAppStateDurationsTracker<AppFGSPolicy, Pac 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 @@ final class AppFGSTracker extends BaseAppStateDurationsTracker<AppFGSPolicy, Pac 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 @@ final class AppFGSTracker extends BaseAppStateDurationsTracker<AppFGSPolicy, Pac 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 @@ final class AppFGSTracker extends BaseAppStateDurationsTracker<AppFGSPolicy, Pac 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 @@ final class AppFGSTracker extends BaseAppStateDurationsTracker<AppFGSPolicy, Pac } } + @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 69f70ca0d0e0..622d7465d4bf 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.AppRestrictionController.DEVICE_CONFIG_SUBNA 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 @@ final class AppPermissionTracker extends BaseAppStateTracker<AppPermissionPolicy 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 @@ final class AppPermissionTracker extends BaseAppStateTracker<AppPermissionPolicy 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 class AppPermissionTracker extends BaseAppStateTracker<AppPermissionPolicy 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 @@ final class AppPermissionTracker extends BaseAppStateTracker<AppPermissionPolicy } } + 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 @@ final class AppPermissionTracker extends BaseAppStateTracker<AppPermissionPolicy } } + /** + * 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 @@ final class AppPermissionTracker extends BaseAppStateTracker<AppPermissionPolicy 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 @@ final class AppPermissionTracker extends BaseAppStateTracker<AppPermissionPolicy 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 @@ final class AppPermissionTracker extends BaseAppStateTracker<AppPermissionPolicy 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 @@ final class AppPermissionTracker extends BaseAppStateTracker<AppPermissionPolicy } } - 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 @@ final class AppPermissionTracker extends BaseAppStateTracker<AppPermissionPolicy 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 dc8403aea1b3..15484b2d618e 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.Slog; 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 @@ public final class AppRestrictionController { } } + 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 0fada53d622e..2f76e2497834 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.media.session.MediaSessionManager; 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 @@ public abstract class BaseAppStateTracker<T extends BaseAppStatePolicy> { 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 @@ public abstract class BaseAppStateTracker<T extends BaseAppStatePolicy> { 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 @@ public abstract class BaseAppStateTracker<T extends BaseAppStatePolicy> { mInjector.getPolicy().dump(pw, " " + prefix); } + void dumpAsProto(ProtoOutputStream proto, int uid) { + } + static class Injector<T extends BaseAppStatePolicy> { T mAppStatePolicy; @@ -266,6 +277,7 @@ public abstract class BaseAppStateTracker<T extends BaseAppStatePolicy> { MediaSessionManager mMediaSessionManager; RoleManager mRoleManager; NotificationManagerInternal mNotificationManagerInternal; + IAppOpsService mIAppOpsService; void setPolicy(T policy) { mAppStatePolicy = policy; @@ -288,6 +300,8 @@ public abstract class BaseAppStateTracker<T extends BaseAppStatePolicy> { 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 @@ public abstract class BaseAppStateTracker<T extends BaseAppStatePolicy> { 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 1131fa8a32b8..4fdc88d3fd64 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 @@ class BatteryExternalStatsWorker implements BatteryStatsImpl.ExternalStatsSync { // 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 7ed3dcf40f65..9626bbe0b4b2 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 @@ public class OomAdjuster { uids.clear(); uids.put(uidRec.getUid(), uidRec); updateUidsLSP(uids, SystemClock.elapsedRealtime()); - mProcessList.incrementProcStateSeqAndNotifyAppsLOSP(uids); } } @@ -1144,8 +1143,6 @@ public class OomAdjuster { } } - mProcessList.incrementProcStateSeqAndNotifyAppsLOSP(activeUids); - return mService.mAppProfiler.updateLowMemStateLSP(numCached, numEmpty, numTrimming); } @@ -1180,6 +1177,11 @@ public class OomAdjuster { @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 b73cf5b20ec0..42a7423725a3 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 @@ final class AmbientContextManagerPerUserService extends 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 010bf1b4cfb8..e2b22dc1bd3d 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 @@ final class AmbientContextShellCommand extends ShellCommand { 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 @@ final class AmbientContextShellCommand extends ShellCommand { 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 @@ final class AmbientContextShellCommand extends ShellCommand { 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 e9205230a4ad..b38195aed250 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 @@ final class GameServiceProviderInstanceImpl implements GameServiceProviderInstan 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 @@ final class GameServiceProviderInstanceImpl implements GameServiceProviderInstan } @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 @@ final class GameServiceProviderInstanceImpl implements GameServiceProviderInstan 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 @@ final class GameServiceProviderInstanceImpl implements GameServiceProviderInstan 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 567d1aef3272..d16fe1240d0c 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.FileDescriptor; 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 @@ public class AttentionManagerService extends SystemService { /** 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 @@ public class AttentionManagerService extends SystemService { @GuardedBy("mLock") private boolean mBinding; private AttentionHandler mAttentionHandler; + private CountDownLatch mServiceBindingLatch; @VisibleForTesting ComponentName mComponentName; @@ -161,6 +167,7 @@ public class AttentionManagerService extends SystemService { mLock = lock; mAttentionHandler = handler; mPrivacyManager = SensorPrivacyManager.getInstance(context); + mServiceBindingLatch = new CountDownLatch(1); } @Override @@ -275,13 +282,16 @@ public class AttentionManagerService extends SystemService { } 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 @@ public class AttentionManagerService extends SystemService { // 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 @@ public class AttentionManagerService extends SystemService { 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 @@ public class AttentionManagerService extends SystemService { @Override public void onServiceConnected(ComponentName name, IBinder service) { init(IAttentionService.Stub.asInterface(service)); + mServiceBindingLatch.countDown(); } @Override @@ -730,6 +752,7 @@ public class AttentionManagerService extends SystemService { 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 d01be5820d34..309a4ff16753 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.IRecordingConfigDispatcher; 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 @@ public class AudioService extends IAudioService.Stub 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 @@ public class AudioService extends IAudioService.Stub 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 193cc5f679af..f0f04e27b7de 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.INativeSpatializerCallback; 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 @@ public class SpatializerHelper { 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 @@ public class SpatializerHelper { 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 @@ public class SpatializerHelper { */ 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 @@ public class SpatializerHelper { 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 @@ public class SpatializerHelper { 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 @@ public class SpatializerHelper { 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 @@ public class SpatializerHelper { return false; } + synchronized boolean isHeadTrackerAvailable() { + return mHeadTrackerAvailable; + } + private boolean checkSpatForHeadTracking(String funcName) { switch (mState) { case STATE_UNINITIALIZED: @@ -1104,7 +1129,7 @@ public class SpatializerHelper { } break; } - return true; + return mIsHeadTrackingSupported; } private void dispatchActualHeadTrackingMode(int newMode) { @@ -1114,7 +1139,8 @@ public class SpatializerHelper { 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 @@ public class SpatializerHelper { 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 @@ public class SpatializerHelper { 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 @@ public class SpatializerHelper { 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 1b2e606117e7..1370fd83f6a8 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 @@ import java.util.NoSuchElementException; */ 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 @@ public abstract class BaseClientMonitor implements IBinder.DeathRecipient { } /** + * 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 @@ public abstract class BaseClientMonitor implements IBinder.DeathRecipient { } /** 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 d0ec4470d3e6..19a93f30937f 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 @@ public class BiometricScheduler { // 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 @@ public class BiometricScheduler { 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 15f0cadced99..968146a166ed 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 @@ public class BiometricSchedulerOperation { * * @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 @@ public class BiometricSchedulerOperation { /** * 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 008717899aba..aeb6b6e2a907 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 @@ public final class SensorOverlays { }; 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 4f900208841e..a0999771a1be 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 @@ public class UserAwareBiometricScheduler extends BiometricScheduler { @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 7765ab3b8e53..9ae6750dbcbf 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 @@ class FaceAuthenticationClient extends AuthenticationClient<AidlSession> 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 efedcf815228..ded18100e458 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 @@ public class FaceDetectClient extends AcquisitionClient<AidlSession> implements 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 8d76e9f031f7..1935a5b135d7 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 @@ class FaceAuthenticationClient extends AuthenticationClient<IBiometricsFace> { 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 b4befd23671f..e8d8fb828542 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 @@ public class FingerprintService extends SystemService { } @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 @@ public class FingerprintService extends SystemService { 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 @@ public class FingerprintService extends SystemService { 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 @@ public class FingerprintService extends SystemService { 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 0bdc4ebad66e..9cdbdc9158fb 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 @@ public interface ServiceProvider { 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 f810bca9707d..1fac8a8ce5c9 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 @@ public class FingerprintProvider implements IBinder.DeathRecipient, ServiceProvi } @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 9d60859a4a21..1d2a3655021c 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 @@ public class Fingerprint21 implements IHwBinder.DeathRecipient, ServiceProvider } @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 149526f21fdb..a4e343e786c1 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 @@ public class Fingerprint21UdfpsMock extends Fingerprint21 implements TrustManage } @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 @@ public class Fingerprint21UdfpsMock extends Fingerprint21 implements TrustManage } @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 c0df095c3289..a6da4a6a4260 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.RouteInfo; 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 @@ public class Vpn { } } + 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 fadcce9ee9b3..954b9307a3ef 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 static android.content.PermissionChecker.PERMISSION_GRANTED; 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.ActivityManager; 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 @@ public final class ContentService extends IContentService.Stub { */ 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 @@ public final class ContentService extends IContentService.Stub { 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 @@ public final class ContentService extends IContentService.Stub { 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 @@ public final class ContentService extends IContentService.Stub { 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 @@ public final class ContentService extends IContentService.Stub { @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 @@ public final class ContentService extends IContentService.Stub { "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 @@ public final class ContentService extends IContentService.Stub { "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 @@ public final class ContentService extends IContentService.Stub { 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 @@ public final class ContentService extends IContentService.Stub { 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 @@ public final class ContentService extends IContentService.Stub { } 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 @@ public final class ContentService extends IContentService.Stub { "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 @@ public final class ContentService extends IContentService.Stub { 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 final class ContentService extends IContentService.Stub { 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 @@ public final class ContentService extends IContentService.Stub { "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 @@ public final class ContentService extends IContentService.Stub { "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 @@ public final class ContentService extends IContentService.Stub { 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 7cb29215b5bf..cb04ddfd636d 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 @@ final class ColorFade { 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 7a0cf4b592e7..540ae8165dbd 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 @@ final class LocalDisplayAdapter extends DisplayAdapter { 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 @@ final class LocalDisplayAdapter extends DisplayAdapter { super(syncRoot, context, handler, listener, TAG); mInjector = injector; mSurfaceControlProxy = mInjector.getSurfaceControlProxy(); + mIsBootDisplayModeSupported = mSurfaceControlProxy.getBootDisplayModeSupport(); } @Override @@ -349,8 +352,7 @@ final class LocalDisplayAdapter extends DisplayAdapter { 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 @@ final class LocalDisplayAdapter extends DisplayAdapter { } 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 22d32a665611..50f5536d9f4b 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 @@ public final class DreamManagerService extends SystemService { } 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/inputmethod/InputMethodManagerService.java b/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java index 77dcbd3e9277..c91608a66481 100644 --- a/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java +++ b/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java @@ -49,6 +49,7 @@ import static android.view.WindowManager.DISPLAY_IME_POLICY_HIDE; import static android.view.WindowManager.DISPLAY_IME_POLICY_LOCAL; import static com.android.server.inputmethod.InputMethodBindingController.TIME_TO_RECONNECT; +import static com.android.server.inputmethod.InputMethodUtils.isSoftInputModeStateVisibleAllowed; import static java.lang.annotation.RetentionPolicy.SOURCE; @@ -187,6 +188,8 @@ import com.android.server.statusbar.StatusBarManagerService; import com.android.server.utils.PriorityDump; import com.android.server.wm.WindowManagerInternal; +import com.google.android.collect.Sets; + import java.io.FileDescriptor; import java.io.IOException; import java.io.PrintWriter; @@ -201,6 +204,7 @@ import java.util.List; import java.util.Locale; import java.util.Objects; import java.util.OptionalInt; +import java.util.Set; import java.util.WeakHashMap; import java.util.concurrent.CopyOnWriteArrayList; import java.util.concurrent.atomic.AtomicInteger; @@ -267,6 +271,14 @@ public final class InputMethodManagerService extends IInputMethodManager.Stub */ private final boolean mPreventImeStartupUnlessTextEditor; + /** + * These IMEs are known not to behave well when evicted from memory and thus are exempt + * from the IME startup avoidance behavior that is enabled by + * {@link #mPreventImeStartupUnlessTextEditor}. + */ + @NonNull + private final Set<String> mNonPreemptibleInputMethods; + @UserIdInt private int mLastSwitchUserId; @@ -1692,6 +1704,8 @@ public final class InputMethodManagerService extends IInputMethodManager.Stub mBindingController = new InputMethodBindingController(this); mPreventImeStartupUnlessTextEditor = mRes.getBoolean( com.android.internal.R.bool.config_preventImeStartupUnlessTextEditor); + mNonPreemptibleInputMethods = Sets.newHashSet(mRes.getStringArray( + com.android.internal.R.array.config_nonPreemptibleInputMethods)); mHwController = new HandwritingModeController(thread.getLooper(), new InkWindowInitializer()); } @@ -2548,7 +2562,7 @@ public final class InputMethodManagerService extends IInputMethodManager.Stub @StartInputFlags int startInputFlags, @StartInputReason int startInputReason, int unverifiedTargetSdkVersion) { // If no method is currently selected, do nothing. - String selectedMethodId = getSelectedMethodIdLocked(); + final String selectedMethodId = getSelectedMethodIdLocked(); if (selectedMethodId == null) { return InputBindResult.NO_IME; } @@ -2592,10 +2606,8 @@ public final class InputMethodManagerService extends IInputMethodManager.Stub mCurAttribute = attribute; // If configured, we want to avoid starting up the IME if it is not supposed to be showing - if (mPreventImeStartupUnlessTextEditor - && !InputMethodUtils.isSoftInputModeStateVisibleAllowed(unverifiedTargetSdkVersion, - startInputFlags) - && !mShowRequested) { + if (shouldPreventImeStartupLocked(selectedMethodId, startInputFlags, + unverifiedTargetSdkVersion)) { if (DEBUG) { Slog.d(TAG, "Avoiding IME startup and unbinding current input method."); } @@ -2637,6 +2649,34 @@ public final class InputMethodManagerService extends IInputMethodManager.Stub } @GuardedBy("ImfLock.class") + private boolean shouldPreventImeStartupLocked( + @NonNull String selectedMethodId, + @StartInputFlags int startInputFlags, + int unverifiedTargetSdkVersion) { + // Fast-path for the majority of cases + if (!mPreventImeStartupUnlessTextEditor) { + return false; + } + + final boolean imeVisibleAllowed = + isSoftInputModeStateVisibleAllowed(unverifiedTargetSdkVersion, startInputFlags); + + return !(imeVisibleAllowed + || mShowRequested + || isNonPreemptibleImeLocked(selectedMethodId)); + } + + /** Return {@code true} if the given IME is non-preemptible like the tv remote service. */ + @GuardedBy("ImfLock.class") + private boolean isNonPreemptibleImeLocked(@NonNull String selectedMethodId) { + final InputMethodInfo imi = mMethodMap.get(selectedMethodId); + if (imi != null) { + return mNonPreemptibleInputMethods.contains(imi.getPackageName()); + } + return false; + } + + @GuardedBy("ImfLock.class") private boolean isSelectedMethodBoundLocked() { String curId = getCurIdLocked(); return curId != null && curId.equals(getSelectedMethodIdLocked()) @@ -3826,7 +3866,7 @@ public final class InputMethodManagerService extends IInputMethodManager.Stub case LayoutParams.SOFT_INPUT_STATE_VISIBLE: if ((softInputMode & LayoutParams.SOFT_INPUT_IS_FORWARD_NAVIGATION) != 0) { if (DEBUG) Slog.v(TAG, "Window asks to show input going forward"); - if (InputMethodUtils.isSoftInputModeStateVisibleAllowed( + if (isSoftInputModeStateVisibleAllowed( unverifiedTargetSdkVersion, startInputFlags)) { if (attribute != null) { res = startInputUncheckedLocked(cs, inputContext, attribute, @@ -3844,7 +3884,7 @@ public final class InputMethodManagerService extends IInputMethodManager.Stub break; case LayoutParams.SOFT_INPUT_STATE_ALWAYS_VISIBLE: if (DEBUG) Slog.v(TAG, "Window asks to always show input"); - if (InputMethodUtils.isSoftInputModeStateVisibleAllowed( + if (isSoftInputModeStateVisibleAllowed( unverifiedTargetSdkVersion, startInputFlags)) { if (!sameWindowFocused) { if (attribute != null) { diff --git a/services/core/java/com/android/server/locales/LocaleManagerService.java b/services/core/java/com/android/server/locales/LocaleManagerService.java index 176c08c8da29..924db6a49eeb 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.Manifest; 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 @@ public class LocaleManagerService extends SystemService { } @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 @@ public class LocaleManagerService extends SystemService { 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 27d2851a1bbe..160542b6aa0f 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 be702d906d3b..ca2ff60203ca 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 @@ package com.android.server.location; 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 @@ public final class LocationPermissions { * 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 52834cb5917d..135af2d73904 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 @@ public class LockSettingsService extends ILockSettings.Stub { 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 @@ public class LockSettingsService extends ILockSettings.Stub { 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 @@ public class LockSettingsService extends ILockSettings.Stub { } 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 @@ public class LockSettingsService extends ILockSettings.Stub { }); } - 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/logcat/LogAccessDialogActivity.java b/services/core/java/com/android/server/logcat/LogAccessDialogActivity.java index 7116ca30c5a9..8be90e0cc622 100644 --- a/services/core/java/com/android/server/logcat/LogAccessDialogActivity.java +++ b/services/core/java/com/android/server/logcat/LogAccessDialogActivity.java @@ -22,6 +22,7 @@ import android.content.Context; import android.content.Intent; import android.content.pm.PackageManager; import android.content.pm.PackageManager.NameNotFoundException; +import android.os.Build; import android.os.Bundle; import android.os.Handler; import android.os.RemoteException; @@ -56,7 +57,7 @@ public class LogAccessDialogActivity extends Activity implements private AlertDialog.Builder mAlertDialog; private AlertDialog mAlert; - private static final int DIALOG_TIME_OUT = 300000; + private static final int DIALOG_TIME_OUT = Build.IS_DEBUGGABLE ? 60000 : 300000; private static final int MSG_DISMISS_DIALOG = 0; 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 3ce8e4659737..1937852fa333 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.RemoteException; 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 @@ public final class MediaProjectionManagerService extends SystemService 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 @@ public final class MediaProjectionManagerService extends SystemService } } - @Override + @Override // Binder call public void registerCallback(IMediaProjectionCallback callback) { if (callback == null) { throw new IllegalArgumentException("callback must not be null"); @@ -576,7 +578,7 @@ public final class MediaProjectionManagerService extends SystemService 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 @@ public final class MediaProjectionManagerService extends SystemService 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 9f573c2ec7a8..0a34eedd47cb 100644 --- a/services/core/java/com/android/server/net/NetworkPolicyManagerService.java +++ b/services/core/java/com/android/server/net/NetworkPolicyManagerService.java @@ -90,6 +90,8 @@ import static android.net.NetworkPolicyManager.RULE_REJECT_METERED; import static android.net.NetworkPolicyManager.RULE_REJECT_RESTRICTED_MODE; import static android.net.NetworkPolicyManager.RULE_TEMPORARY_ALLOW_METERED; import static android.net.NetworkPolicyManager.SUBSCRIPTION_OVERRIDE_UNMETERED; +import static android.net.NetworkPolicyManager.allowedReasonsToString; +import static android.net.NetworkPolicyManager.blockedReasonsToString; import static android.net.NetworkPolicyManager.isProcStateAllowedWhileIdleOrPowerSaveMode; import static android.net.NetworkPolicyManager.isProcStateAllowedWhileInLowPowerStandby; import static android.net.NetworkPolicyManager.isProcStateAllowedWhileOnRestrictBackground; @@ -594,7 +596,7 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub { @GuardedBy("mUidRulesFirstLock") private final SparseArray<UidState> mUidState = new SparseArray<>(); - @GuardedBy("mUidRulesFirstLock") + @GuardedBy("mUidBlockedState") private final SparseArray<UidBlockedState> mUidBlockedState = new SparseArray<>(); /** Objects used temporarily while computing the new blocked state for each uid. */ @@ -3930,7 +3932,9 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub { final SparseBooleanArray knownUids = new SparseBooleanArray(); collectKeys(mUidState, knownUids); - collectKeys(mUidBlockedState, knownUids); + synchronized (mUidBlockedState) { + collectKeys(mUidBlockedState, knownUids); + } fout.println("Status for all known UIDs:"); fout.increaseIndent(); @@ -3948,12 +3952,14 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub { fout.print(uidState.toString()); } - final UidBlockedState uidBlockedState = mUidBlockedState.get(uid); - if (uidBlockedState == null) { - fout.print(" blocked_state={null}"); - } else { - fout.print(" blocked_state="); - fout.print(uidBlockedState.toString()); + synchronized (mUidBlockedState) { + final UidBlockedState uidBlockedState = mUidBlockedState.get(uid); + if (uidBlockedState == null) { + fout.print(" blocked_state={null}"); + } else { + fout.print(" blocked_state="); + fout.print(uidBlockedState); + } } fout.println(); } @@ -4094,7 +4100,7 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub { "updateNetworkStats: " + uid + "/" + (uidForeground ? "F" : "B")); } try { - mNetworkStats.setUidForeground(uid, uidForeground); + mNetworkStats.noteUidForeground(uid, uidForeground); } finally { Trace.traceEnd(Trace.TRACE_TAG_NETWORK); } @@ -4128,9 +4134,9 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub { mUidFirewallRestrictedModeRules.clear(); forEachUid("updateRestrictedModeAllowlist", uid -> { synchronized (mUidRulesFirstLock) { - final UidBlockedState uidBlockedState = updateBlockedReasonsForRestrictedModeUL( + final int effectiveBlockedReasons = updateBlockedReasonsForRestrictedModeUL( uid); - final int newFirewallRule = getRestrictedModeFirewallRule(uidBlockedState); + final int newFirewallRule = getRestrictedModeFirewallRule(effectiveBlockedReasons); // setUidFirewallRulesUL will allowlist all uids that are passed to it, so only add // non-default rules. @@ -4150,7 +4156,7 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub { @VisibleForTesting @GuardedBy("mUidRulesFirstLock") void updateRestrictedModeForUidUL(int uid) { - final UidBlockedState uidBlockedState = updateBlockedReasonsForRestrictedModeUL(uid); + final int effectiveBlockedReasons = updateBlockedReasonsForRestrictedModeUL(uid); // if restricted networking mode is on, and the app has an access exemption, the uid rule // will not change, but the firewall rule will have to be updated. @@ -4158,37 +4164,48 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub { // Note: setUidFirewallRule also updates mUidFirewallRestrictedModeRules. // In this case, default firewall rules can also be added. setUidFirewallRuleUL(FIREWALL_CHAIN_RESTRICTED, uid, - getRestrictedModeFirewallRule(uidBlockedState)); + getRestrictedModeFirewallRule(effectiveBlockedReasons)); } } @GuardedBy("mUidRulesFirstLock") - private UidBlockedState updateBlockedReasonsForRestrictedModeUL(int uid) { - final UidBlockedState uidBlockedState = getOrCreateUidBlockedStateForUid( - mUidBlockedState, uid); - final int oldEffectiveBlockedReasons = uidBlockedState.effectiveBlockedReasons; - if (mRestrictedNetworkingMode) { - uidBlockedState.blockedReasons |= BLOCKED_REASON_RESTRICTED_MODE; - } else { - uidBlockedState.blockedReasons &= ~BLOCKED_REASON_RESTRICTED_MODE; - } - if (hasRestrictedModeAccess(uid)) { - uidBlockedState.allowedReasons |= ALLOWED_REASON_RESTRICTED_MODE_PERMISSIONS; - } else { - uidBlockedState.allowedReasons &= ~ALLOWED_REASON_RESTRICTED_MODE_PERMISSIONS; + private int updateBlockedReasonsForRestrictedModeUL(int uid) { + final boolean hasRestrictedModeAccess = hasRestrictedModeAccess(uid); + final int oldEffectiveBlockedReasons; + final int newEffectiveBlockedReasons; + final int uidRules; + synchronized (mUidBlockedState) { + final UidBlockedState uidBlockedState = getOrCreateUidBlockedStateForUid( + mUidBlockedState, uid); + oldEffectiveBlockedReasons = uidBlockedState.effectiveBlockedReasons; + if (mRestrictedNetworkingMode) { + uidBlockedState.blockedReasons |= BLOCKED_REASON_RESTRICTED_MODE; + } else { + uidBlockedState.blockedReasons &= ~BLOCKED_REASON_RESTRICTED_MODE; + } + if (hasRestrictedModeAccess) { + uidBlockedState.allowedReasons |= ALLOWED_REASON_RESTRICTED_MODE_PERMISSIONS; + } else { + uidBlockedState.allowedReasons &= ~ALLOWED_REASON_RESTRICTED_MODE_PERMISSIONS; + } + uidBlockedState.updateEffectiveBlockedReasons(); + + newEffectiveBlockedReasons = uidBlockedState.effectiveBlockedReasons; + uidRules = oldEffectiveBlockedReasons == newEffectiveBlockedReasons + ? RULE_NONE + : uidBlockedState.deriveUidRules(); } - uidBlockedState.updateEffectiveBlockedReasons(); - if (oldEffectiveBlockedReasons != uidBlockedState.effectiveBlockedReasons) { + if (oldEffectiveBlockedReasons != newEffectiveBlockedReasons) { postBlockedReasonsChangedMsg(uid, - uidBlockedState.effectiveBlockedReasons, oldEffectiveBlockedReasons); + newEffectiveBlockedReasons, oldEffectiveBlockedReasons); - postUidRulesChangedMsg(uid, uidBlockedState.deriveUidRules()); + postUidRulesChangedMsg(uid, uidRules); } - return uidBlockedState; + return newEffectiveBlockedReasons; } - private static int getRestrictedModeFirewallRule(UidBlockedState uidBlockedState) { - if ((uidBlockedState.effectiveBlockedReasons & BLOCKED_REASON_RESTRICTED_MODE) != 0) { + private static int getRestrictedModeFirewallRule(int effectiveBlockedReasons) { + if ((effectiveBlockedReasons & BLOCKED_REASON_RESTRICTED_MODE) != 0) { // rejected in restricted mode, this is the default behavior. return FIREWALL_RULE_DEFAULT; } else { @@ -4292,12 +4309,10 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub { mUidFirewallLowPowerStandbyModeRules.clear(); for (int i = mUidState.size() - 1; i >= 0; i--) { final int uid = mUidState.keyAt(i); - UidBlockedState uidBlockedState = mUidBlockedState.get(uid); - if (hasInternetPermissionUL(uid) && uidBlockedState != null - && (uidBlockedState.effectiveBlockedReasons + final int effectiveBlockedReasons = getEffectiveBlockedReasons(uid); + if (hasInternetPermissionUL(uid) && (effectiveBlockedReasons & BLOCKED_REASON_LOW_POWER_STANDBY) == 0) { - mUidFirewallLowPowerStandbyModeRules.put(mUidBlockedState.keyAt(i), - FIREWALL_RULE_ALLOW); + mUidFirewallLowPowerStandbyModeRules.put(uid, FIREWALL_RULE_ALLOW); } } setUidFirewallRulesUL(FIREWALL_CHAIN_LOW_POWER_STANDBY, @@ -4316,10 +4331,9 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub { return; } - final UidBlockedState uidBlockedState = mUidBlockedState.get(uid); - if (mUidState.contains(uid) && uidBlockedState != null - && (uidBlockedState.effectiveBlockedReasons & BLOCKED_REASON_LOW_POWER_STANDBY) - == 0) { + final int effectiveBlockedReasons = getEffectiveBlockedReasons(uid); + if (mUidState.contains(uid) + && (effectiveBlockedReasons & BLOCKED_REASON_LOW_POWER_STANDBY) == 0) { mUidFirewallLowPowerStandbyModeRules.put(uid, FIREWALL_RULE_ALLOW); setUidFirewallRuleUL(FIREWALL_CHAIN_LOW_POWER_STANDBY, uid, FIREWALL_RULE_ALLOW); } else { @@ -4448,9 +4462,8 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub { if (!isUidValidForDenylistRulesUL(uid)) { continue; } - final UidBlockedState uidBlockedState = getOrCreateUidBlockedStateForUid( - mUidBlockedState, uid); - if (!enableChain && (uidBlockedState.blockedReasons & ~BLOCKED_METERED_REASON_MASK) + final int blockedReasons = getBlockedReasons(uid); + if (!enableChain && (blockedReasons & ~BLOCKED_METERED_REASON_MASK) == BLOCKED_REASON_NONE) { // Chain isn't enabled and the uid had no restrictions to begin with. continue; @@ -4692,7 +4705,9 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub { @GuardedBy("mUidRulesFirstLock") private void onUidDeletedUL(int uid) { // First cleanup in-memory state synchronously... - mUidBlockedState.delete(uid); + synchronized (mUidBlockedState) { + mUidBlockedState.delete(uid); + } mUidPolicy.delete(uid); mUidFirewallStandbyRules.delete(uid); mUidFirewallDozableRules.delete(uid); @@ -4804,11 +4819,6 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub { final int uidPolicy = mUidPolicy.get(uid, POLICY_NONE); final boolean isForeground = isUidForegroundOnRestrictBackgroundUL(uid); final boolean isRestrictedByAdmin = isRestrictedByAdminUL(uid); - final UidBlockedState uidBlockedState = getOrCreateUidBlockedStateForUid( - mUidBlockedState, uid); - final UidBlockedState previousUidBlockedState = getOrCreateUidBlockedStateForUid( - mTmpUidBlockedState, uid); - previousUidBlockedState.copyFrom(uidBlockedState); final boolean isDenied = (uidPolicy & POLICY_REJECT_METERED_BACKGROUND) != 0; final boolean isAllowed = (uidPolicy & POLICY_ALLOW_METERED_BACKGROUND) != 0; @@ -4823,18 +4833,47 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub { newAllowedReasons |= (isForeground ? ALLOWED_METERED_REASON_FOREGROUND : 0); newAllowedReasons |= (isAllowed ? ALLOWED_METERED_REASON_USER_EXEMPTED : 0); - uidBlockedState.blockedReasons = (uidBlockedState.blockedReasons - & ~BLOCKED_METERED_REASON_MASK) | newBlockedReasons; - uidBlockedState.allowedReasons = (uidBlockedState.allowedReasons - & ~ALLOWED_METERED_REASON_MASK) | newAllowedReasons; - uidBlockedState.updateEffectiveBlockedReasons(); - final int oldEffectiveBlockedReasons = previousUidBlockedState.effectiveBlockedReasons; - final int newEffectiveBlockedReasons = uidBlockedState.effectiveBlockedReasons; + final int oldEffectiveBlockedReasons; + final int newEffectiveBlockedReasons; + final int oldAllowedReasons; + final int uidRules; + synchronized (mUidBlockedState) { + final UidBlockedState uidBlockedState = getOrCreateUidBlockedStateForUid( + mUidBlockedState, uid); + final UidBlockedState previousUidBlockedState = getOrCreateUidBlockedStateForUid( + mTmpUidBlockedState, uid); + previousUidBlockedState.copyFrom(uidBlockedState); + + uidBlockedState.blockedReasons = (uidBlockedState.blockedReasons + & ~BLOCKED_METERED_REASON_MASK) | newBlockedReasons; + uidBlockedState.allowedReasons = (uidBlockedState.allowedReasons + & ~ALLOWED_METERED_REASON_MASK) | newAllowedReasons; + uidBlockedState.updateEffectiveBlockedReasons(); + + oldEffectiveBlockedReasons = previousUidBlockedState.effectiveBlockedReasons; + newEffectiveBlockedReasons = uidBlockedState.effectiveBlockedReasons; + oldAllowedReasons = previousUidBlockedState.allowedReasons; + uidRules = (oldEffectiveBlockedReasons == newEffectiveBlockedReasons) + ? RULE_NONE : uidBlockedState.deriveUidRules(); + + if (LOGV) { + Log.v(TAG, "updateRuleForRestrictBackgroundUL(" + uid + ")" + + ": isForeground=" + isForeground + + ", isDenied=" + isDenied + + ", isAllowed=" + isAllowed + + ", isRestrictedByAdmin=" + isRestrictedByAdmin + + ", oldBlockedState=" + previousUidBlockedState + + ", newBlockedState=" + uidBlockedState + + ", newBlockedMeteredReasons=" + blockedReasonsToString(newBlockedReasons) + + ", newAllowedMeteredReasons=" + allowedReasonsToString( + newAllowedReasons)); + } + } if (oldEffectiveBlockedReasons != newEffectiveBlockedReasons) { postBlockedReasonsChangedMsg(uid, newEffectiveBlockedReasons, oldEffectiveBlockedReasons); - postUidRulesChangedMsg(uid, uidBlockedState.deriveUidRules()); + postUidRulesChangedMsg(uid, uidRules); } // Note that the conditionals below are for avoiding unnecessary calls to netd. @@ -4850,29 +4889,11 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub { } final int allowlistReasons = ALLOWED_METERED_REASON_FOREGROUND | ALLOWED_METERED_REASON_USER_EXEMPTED; - final int oldAllowedReasons = previousUidBlockedState.allowedReasons; if ((oldAllowedReasons & allowlistReasons) != ALLOWED_REASON_NONE || (newAllowedReasons & allowlistReasons) != ALLOWED_REASON_NONE) { setMeteredNetworkAllowlist(uid, (newAllowedReasons & allowlistReasons) != ALLOWED_REASON_NONE); } - - if (LOGV) { - Log.v(TAG, "updateRuleForRestrictBackgroundUL(" + uid + ")" - + ": isForeground=" +isForeground - + ", isDenied=" + isDenied - + ", isAllowed=" + isAllowed - + ", isRestrictedByAdmin=" + isRestrictedByAdmin - + ", oldBlockedState=" + previousUidBlockedState.toString() - + ", newBlockedState=" + uidBlockedState.toString() - + ", oldBlockedMeteredReasons=" + NetworkPolicyManager.blockedReasonsToString( - uidBlockedState.blockedReasons & BLOCKED_METERED_REASON_MASK) - + ", oldBlockedMeteredEffectiveReasons=" - + NetworkPolicyManager.blockedReasonsToString( - uidBlockedState.effectiveBlockedReasons & BLOCKED_METERED_REASON_MASK) - + ", oldAllowedMeteredReasons=" + NetworkPolicyManager.blockedReasonsToString( - uidBlockedState.allowedReasons & BLOCKED_METERED_REASON_MASK)); - } } /** @@ -4932,56 +4953,66 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub { final boolean isWhitelisted = isWhitelistedFromPowerSaveUL(uid, mDeviceIdleMode); - final UidBlockedState uidBlockedState = getOrCreateUidBlockedStateForUid( - mUidBlockedState, uid); - final UidBlockedState previousUidBlockedState = getOrCreateUidBlockedStateForUid( - mTmpUidBlockedState, uid); - previousUidBlockedState.copyFrom(uidBlockedState); - - int newBlockedReasons = BLOCKED_REASON_NONE; - int newAllowedReasons = ALLOWED_REASON_NONE; - newBlockedReasons |= (mRestrictPower ? BLOCKED_REASON_BATTERY_SAVER : 0); - newBlockedReasons |= (mDeviceIdleMode ? BLOCKED_REASON_DOZE : 0); - newBlockedReasons |= (mLowPowerStandbyActive ? BLOCKED_REASON_LOW_POWER_STANDBY : 0); - newBlockedReasons |= (isUidIdle ? BLOCKED_REASON_APP_STANDBY : 0); - newBlockedReasons |= (uidBlockedState.blockedReasons & BLOCKED_REASON_RESTRICTED_MODE); - - newAllowedReasons |= (isSystem(uid) ? ALLOWED_REASON_SYSTEM : 0); - newAllowedReasons |= (isForeground ? ALLOWED_REASON_FOREGROUND : 0); - newAllowedReasons |= (isTop ? ALLOWED_REASON_TOP : 0); - newAllowedReasons |= (isWhitelistedFromPowerSaveUL(uid, true) - ? ALLOWED_REASON_POWER_SAVE_ALLOWLIST : 0); - newAllowedReasons |= (isWhitelistedFromPowerSaveExceptIdleUL(uid) - ? ALLOWED_REASON_POWER_SAVE_EXCEPT_IDLE_ALLOWLIST : 0); - newAllowedReasons |= (uidBlockedState.allowedReasons - & ALLOWED_REASON_RESTRICTED_MODE_PERMISSIONS); - newAllowedReasons |= (isAllowlistedFromLowPowerStandbyUL(uid)) - ? ALLOWED_REASON_LOW_POWER_STANDBY_ALLOWLIST : 0; - - uidBlockedState.blockedReasons = (uidBlockedState.blockedReasons - & BLOCKED_METERED_REASON_MASK) | newBlockedReasons; - uidBlockedState.allowedReasons = (uidBlockedState.allowedReasons - & ALLOWED_METERED_REASON_MASK) | newAllowedReasons; - uidBlockedState.updateEffectiveBlockedReasons(); - if (previousUidBlockedState.effectiveBlockedReasons - != uidBlockedState.effectiveBlockedReasons) { - postBlockedReasonsChangedMsg(uid, - uidBlockedState.effectiveBlockedReasons, - previousUidBlockedState.effectiveBlockedReasons); + final int oldEffectiveBlockedReasons; + final int newEffectiveBlockedReasons; + final int uidRules; + synchronized (mUidBlockedState) { + final UidBlockedState uidBlockedState = getOrCreateUidBlockedStateForUid( + mUidBlockedState, uid); + final UidBlockedState previousUidBlockedState = getOrCreateUidBlockedStateForUid( + mTmpUidBlockedState, uid); + previousUidBlockedState.copyFrom(uidBlockedState); + + int newBlockedReasons = BLOCKED_REASON_NONE; + int newAllowedReasons = ALLOWED_REASON_NONE; + newBlockedReasons |= (mRestrictPower ? BLOCKED_REASON_BATTERY_SAVER : 0); + newBlockedReasons |= (mDeviceIdleMode ? BLOCKED_REASON_DOZE : 0); + newBlockedReasons |= (mLowPowerStandbyActive ? BLOCKED_REASON_LOW_POWER_STANDBY : 0); + newBlockedReasons |= (isUidIdle ? BLOCKED_REASON_APP_STANDBY : 0); + newBlockedReasons |= (uidBlockedState.blockedReasons & BLOCKED_REASON_RESTRICTED_MODE); + + newAllowedReasons |= (isSystem(uid) ? ALLOWED_REASON_SYSTEM : 0); + newAllowedReasons |= (isForeground ? ALLOWED_REASON_FOREGROUND : 0); + newAllowedReasons |= (isTop ? ALLOWED_REASON_TOP : 0); + newAllowedReasons |= (isWhitelistedFromPowerSaveUL(uid, true) + ? ALLOWED_REASON_POWER_SAVE_ALLOWLIST : 0); + newAllowedReasons |= (isWhitelistedFromPowerSaveExceptIdleUL(uid) + ? ALLOWED_REASON_POWER_SAVE_EXCEPT_IDLE_ALLOWLIST : 0); + newAllowedReasons |= (uidBlockedState.allowedReasons + & ALLOWED_REASON_RESTRICTED_MODE_PERMISSIONS); + newAllowedReasons |= (isAllowlistedFromLowPowerStandbyUL(uid)) + ? ALLOWED_REASON_LOW_POWER_STANDBY_ALLOWLIST : 0; + + uidBlockedState.blockedReasons = (uidBlockedState.blockedReasons + & BLOCKED_METERED_REASON_MASK) | newBlockedReasons; + uidBlockedState.allowedReasons = (uidBlockedState.allowedReasons + & ALLOWED_METERED_REASON_MASK) | newAllowedReasons; + uidBlockedState.updateEffectiveBlockedReasons(); - postUidRulesChangedMsg(uid, uidBlockedState.deriveUidRules()); + if (LOGV) { + Log.v(TAG, "updateRulesForPowerRestrictionsUL(" + uid + ")" + + ", isIdle: " + isUidIdle + + ", mRestrictPower: " + mRestrictPower + + ", mDeviceIdleMode: " + mDeviceIdleMode + + ", isForeground=" + isForeground + + ", isTop=" + isTop + + ", isWhitelisted=" + isWhitelisted + + ", oldUidBlockedState=" + previousUidBlockedState + + ", newUidBlockedState=" + uidBlockedState); + } + + oldEffectiveBlockedReasons = previousUidBlockedState.effectiveBlockedReasons; + newEffectiveBlockedReasons = uidBlockedState.effectiveBlockedReasons; + uidRules = oldEffectiveBlockedReasons == newEffectiveBlockedReasons + ? RULE_NONE + : uidBlockedState.deriveUidRules(); } + if (oldEffectiveBlockedReasons != newEffectiveBlockedReasons) { + postBlockedReasonsChangedMsg(uid, + oldEffectiveBlockedReasons, + newEffectiveBlockedReasons); - if (LOGV) { - Log.v(TAG, "updateRulesForPowerRestrictionsUL(" + uid + ")" - + ", isIdle: " + isUidIdle - + ", mRestrictPower: " + mRestrictPower - + ", mDeviceIdleMode: " + mDeviceIdleMode - + ", isForeground=" + isForeground - + ", isTop=" + isTop - + ", isWhitelisted=" + isWhitelisted - + ", oldUidBlockedState=" + previousUidBlockedState.toString() - + ", newUidBlockedState=" + uidBlockedState.toString()); + postUidRulesChangedMsg(uid, uidRules); } } @@ -5421,6 +5452,11 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub { 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 +5469,11 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub { 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 +5512,31 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub { } } + 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 +5579,11 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub { 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 +5620,16 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub { */ 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 +5639,9 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub { } catch (RemoteException e) { // ignored; service lives in system_server } + if (Process.isApplicationUid(uid)) { + resetUidFirewallRules(Process.toSdkSandboxUid(uid)); + } } @Deprecated @@ -5728,7 +5797,7 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub { mContext.enforceCallingOrSelfPermission(OBSERVE_NETWORK_POLICY, TAG); int blockedReasons; - synchronized (mUidRulesFirstLock) { + synchronized (mUidBlockedState) { final UidBlockedState uidBlockedState = mUidBlockedState.get(uid); blockedReasons = uidBlockedState == null ? BLOCKED_REASON_NONE : uidBlockedState.effectiveBlockedReasons; @@ -5746,7 +5815,7 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub { @Override public boolean isUidRestrictedOnMeteredNetworks(int uid) { mContext.enforceCallingOrSelfPermission(OBSERVE_NETWORK_POLICY, TAG); - synchronized (mUidRulesFirstLock) { + synchronized (mUidBlockedState) { final UidBlockedState uidBlockedState = mUidBlockedState.get(uid); int blockedReasons = uidBlockedState == null ? BLOCKED_REASON_NONE : uidBlockedState.effectiveBlockedReasons; @@ -5994,10 +6063,6 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub { return restrictedUids != null && restrictedUids.contains(uid); } - private static boolean hasRule(int uidRules, int rule) { - return (uidRules & rule) != 0; - } - private static boolean getBooleanDefeatingNullable(@Nullable PersistableBundle bundle, String key, boolean defaultValue) { return (bundle != null) ? bundle.getBoolean(key, defaultValue) : defaultValue; @@ -6013,16 +6078,39 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub { return uidBlockedState; } + private int getEffectiveBlockedReasons(int uid) { + synchronized (mUidBlockedState) { + final UidBlockedState uidBlockedState = mUidBlockedState.get(uid); + return uidBlockedState == null + ? BLOCKED_REASON_NONE + : uidBlockedState.effectiveBlockedReasons; + } + } + + private int getBlockedReasons(int uid) { + synchronized (mUidBlockedState) { + final UidBlockedState uidBlockedState = mUidBlockedState.get(uid); + return uidBlockedState == null + ? BLOCKED_REASON_NONE + : uidBlockedState.blockedReasons; + } + } + @VisibleForTesting static final class UidBlockedState { public int blockedReasons; public int allowedReasons; public int effectiveBlockedReasons; + private UidBlockedState(int blockedReasons, int allowedReasons, + int effectiveBlockedReasons) { + this.blockedReasons = blockedReasons; + this.allowedReasons = allowedReasons; + this.effectiveBlockedReasons = effectiveBlockedReasons; + } + UidBlockedState() { - blockedReasons = BLOCKED_REASON_NONE; - allowedReasons = ALLOWED_REASON_NONE; - effectiveBlockedReasons = BLOCKED_REASON_NONE; + this(BLOCKED_REASON_NONE, ALLOWED_REASON_NONE, BLOCKED_REASON_NONE); } void updateEffectiveBlockedReasons() { @@ -6259,7 +6347,7 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub { } } if (LOGV) { - Slog.v(TAG, "uidBlockedState=" + this.toString() + Slog.v(TAG, "uidBlockedState=" + this + " -> uidRule=" + uidRulesToString(uidRule)); } return uidRule; diff --git a/services/core/java/com/android/server/notification/PreferencesHelper.java b/services/core/java/com/android/server/notification/PreferencesHelper.java index 1f7d65e6c604..75d7a1f510b9 100644 --- a/services/core/java/com/android/server/notification/PreferencesHelper.java +++ b/services/core/java/com/android/server/notification/PreferencesHelper.java @@ -601,8 +601,10 @@ public class PreferencesHelper implements RankingConfig { out.attribute(null, ATT_NAME, r.pkg); if (!notifPermissions.isEmpty()) { Pair<Integer, String> app = new Pair(r.uid, r.pkg); + final Pair<Boolean, Boolean> permission = notifPermissions.get(app); out.attributeInt(null, ATT_IMPORTANCE, - notifPermissions.get(app).first ? IMPORTANCE_DEFAULT : IMPORTANCE_NONE); + permission != null && permission.first ? IMPORTANCE_DEFAULT + : IMPORTANCE_NONE); notifPermissions.remove(app); } else { if (r.importance != DEFAULT_IMPORTANCE) { diff --git a/services/core/java/com/android/server/notification/ZenModeHelper.java b/services/core/java/com/android/server/notification/ZenModeHelper.java index 93f1b4741bd6..9e0c97502c4f 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 @@ public class ZenModeHelper { // 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 @@ public class ZenModeHelper { 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 bbef237507bf..b41a0b8878e0 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 AppIdSettingMap snapshot() { - AppIdSettingMap l = new AppIdSettingMap(); - snapshot(l, this); - return l; + 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); + } } - /** - * @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; + 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); } - /** - * @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; + // 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 { - return mCurrentMaxAppId + 1; + 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(); + mNonSystemSettings.snapshot(l.mNonSystemSettings, mNonSystemSettings); + mSystemSettings.snapshot(l.mSystemSettings, mSystemSettings); + return l; + } + + 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 9ff4aab83cff..d26a1ac4fba0 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 @@ public final class BackgroundDexOptService { * * <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 @@ public final class BackgroundDexOptService { 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 @@ public final class BackgroundDexOptService { 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 @@ public final class BackgroundDexOptService { } /** 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 @@ public final class BackgroundDexOptService { } @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 @@ public final class BackgroundDexOptService { } } - 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 @@ public final class BackgroundDexOptService { } @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 @@ public final class BackgroundDexOptService { 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 06e827a8897f..54a103959d04 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.PackageInfoUtils; 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 class ComputerEngine implements Computer { 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 b30798485bf7..89f8be27096a 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 @@ public class CrossProfileAppsServiceImpl extends ICrossProfileApps.Stub { 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 @@ public class CrossProfileAppsServiceImpl extends ICrossProfileApps.Stub { 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 @@ public class CrossProfileAppsServiceImpl extends ICrossProfileApps.Stub { } 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 @@ public class CrossProfileAppsServiceImpl extends ICrossProfileApps.Stub { 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 50b2e2321886..bb2ba5cc498d 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 @@ final class DexOptHelper { 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 index 91750dee7688..15f26e7a6d6c 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.SYSTEM_PARTITIONS; 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 @@ import java.util.concurrent.ExecutorService; * 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 @@ final class InitAndSystemPackageHelper { * 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 @@ final class InitAndSystemPackageHelper { 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 @@ final class InitAndSystemPackageHelper { 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 @@ final class InitAndSystemPackageHelper { 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<>(); - - if (!mPm.isOnlyCoreApps()) { + apkInApexPreInstalledPaths.get(pkg.getPackageName())))); + + 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 @@ final class InitAndSystemPackageHelper { 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 @@ final class InitAndSystemPackageHelper { 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 @@ final class InitAndSystemPackageHelper { @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 @@ final class InitAndSystemPackageHelper { 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 b39b24f6defa..870a11ac2d61 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 class InstallPackageHelper { 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 @@ final class InstallPackageHelper { | 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 @@ final class InstallPackageHelper { 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 @@ final class InstallPackageHelper { @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 @@ final class InstallPackageHelper { 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 @@ final class InstallPackageHelper { 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 @@ final class InstallPackageHelper { /** * 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 @@ final class InstallPackageHelper { */ @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 @@ final class InstallPackageHelper { PackageManagerService.renameStaticSharedLibraryPackage(parsedPackage); } - return addForInitLI(parsedPackage, parseFlags, scanFlags, currentTime, user); + return addForInitLI(parsedPackage, parseFlags, scanFlags, user); } /** @@ -3563,11 +3563,11 @@ final class InstallPackageHelper { @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 @@ final class InstallPackageHelper { 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 class InstallPackageHelper { } 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 76b9830cbde9..45c5116bea59 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.CreateAppDataArgs; 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 class Installer extends SystemService { */ 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 @@ public class Installer extends SystemService { 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 @@ public class Installer extends SystemService { } } + 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 @@ public class Installer extends SystemService { } } + /** + * 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 @@ public class Installer extends SystemService { } } + /** + * 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 69d498794e64..27c6d9bec2e8 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 @@ public class PackageDexOptimizer { 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 @@ public class PackageDexOptimizer { } /** + * 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 @@ public class PackageDexOptimizer { 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 @@ public class PackageDexOptimizer { /** * 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 @@ public class PackageDexOptimizer { 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 @@ public class PackageDexOptimizer { } /** - * 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 @@ public class PackageDexOptimizer { } /** - * 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 @@ public class PackageDexOptimizer { 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 @@ public class PackageDexOptimizer { 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 @@ public class PackageDexOptimizer { */ 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 @@ public class PackageDexOptimizer { * 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 @@ public class PackageDexOptimizer { 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 4e702e2c9df5..aa5f39f78cbd 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 @@ public class PackageInstallerService extends IPackageInstaller.Stub implements 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 68be64fdba0d..beb198643e78 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_INTERNAL_ERROR; 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 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub { "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 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub { 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 7b76567fcc6e..39cc37ea2e7c 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 @@ import android.annotation.SystemApi; */ @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 67056ead3423..b1b05bedfcad 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.Parcel; 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.resolution.ComponentResolverApi; 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 @@ public class PackageManagerService implements PackageSender, TestUtilityService 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 @@ public class PackageManagerService implements PackageSender, TestUtilityService 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 @@ public class PackageManagerService implements PackageSender, TestUtilityService 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 @@ public class PackageManagerService implements PackageSender, TestUtilityService 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 @@ public class PackageManagerService implements PackageSender, TestUtilityService } 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 @@ public class PackageManagerService implements PackageSender, TestUtilityService } boolean isExpectingBetter(String packageName) { - return mInitAndSystemPackageHelper.isExpectingBetter(packageName); + return mInitAppsHelper.isExpectingBetter(packageName); } int getDefParseFlags() { @@ -7112,13 +7132,12 @@ public class PackageManagerService implements PackageSender, TestUtilityService } 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 @@ public class PackageManagerService implements PackageSender, TestUtilityService 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 5bdda0b3c1d8..e466fe2c0e31 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 final class PackageManagerServiceTestParams { 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/PackageManagerShellCommand.java b/services/core/java/com/android/server/pm/PackageManagerShellCommand.java index 62e9d372f09d..15753cd24e85 100644 --- a/services/core/java/com/android/server/pm/PackageManagerShellCommand.java +++ b/services/core/java/com/android/server/pm/PackageManagerShellCommand.java @@ -2540,8 +2540,10 @@ class PackageManagerShellCommand extends ShellCommand { privAppPermissions = SystemConfig.getInstance() .getSystemExtPrivAppPermissions(pkg); } else if (isApexApp(pkg)) { + final String apexName = ApexManager.getInstance().getApexModuleNameForPackageName( + getApexPackageNameContainingPackage(pkg)); privAppPermissions = SystemConfig.getInstance() - .getApexPrivAppPermissions(getApexPackageNameContainingPackage(pkg), pkg); + .getApexPrivAppPermissions(apexName, pkg); } else { privAppPermissions = SystemConfig.getInstance().getPrivAppPermissions(pkg); } @@ -2567,8 +2569,10 @@ class PackageManagerShellCommand extends ShellCommand { privAppPermissions = SystemConfig.getInstance() .getSystemExtPrivAppDenyPermissions(pkg); } else if (isApexApp(pkg)) { + final String apexName = ApexManager.getInstance().getApexModuleNameForPackageName( + getApexPackageNameContainingPackage(pkg)); privAppPermissions = SystemConfig.getInstance() - .getApexPrivAppDenyPermissions(getApexPackageNameContainingPackage(pkg), pkg); + .getApexPrivAppDenyPermissions(apexName, pkg); } else { privAppPermissions = SystemConfig.getInstance().getPrivAppDenyPermissions(pkg); } diff --git a/services/core/java/com/android/server/pm/Settings.java b/services/core/java/com/android/server/pm/Settings.java index 6ccaae148ce6..698dbe945e6f 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.Handler; 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 @@ public final class Settings implements Watchable, Snappable { 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 @@ public final class Settings implements Watchable, Snappable { @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 @@ public final class Settings implements Watchable, Snappable { 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 @@ public final class Settings implements Watchable, Snappable { mLock = new PackageManagerTracedLock(); mPackages.putAll(pkgSettings); mAppIds = new AppIdSettingMap(); - mOtherAppIds = new AppIdSettingMap(); mSystemDir = null; mPermissions = null; mRuntimePermissionsPersistence = null; @@ -629,7 +622,6 @@ public final class Settings implements Watchable, Snappable { mLock = lock; mAppIds = new AppIdSettingMap(); - mOtherAppIds = new AppIdSettingMap(); mPermissions = new LegacyPermissionSettings(lock); mRuntimePermissionsPersistence = new RuntimePermissionPersistence( runtimePermissionsPersistence, new Consumer<Integer>() { @@ -710,7 +702,6 @@ public final class Settings implements Watchable, Snappable { 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 @@ public final class Settings implements Watchable, Snappable { 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 @@ public final class Settings implements Watchable, Snappable { 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 @@ public final class Settings implements Watchable, Snappable { } 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 @@ public final class Settings implements Watchable, Snappable { 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 @@ public final class Settings implements Watchable, Snappable { 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 @@ public final class Settings implements Watchable, Snappable { 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); - } - - 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); - } + mAppIds.removeSetting(appId); } - /** * 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 @@ public final class Settings implements Watchable, Snappable { } } - // 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 8921fee6c8e0..c8f809b6782f 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 @@ class ShortcutPackage extends ShortcutPackageItem { 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 1cf2dc52e430..25fe0007ec4b 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 @@ public class ShortcutService extends IShortcutService.Stub { 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 df19d3e58bfd..a991ed3c4792 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 @@ public final class StorageEventHelper extends StorageEventListener { 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 eae7658587f7..70053bdeb47e 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 @@ public class UserManagerService extends IUserManager.Stub { 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 @@ public class UserManagerService extends IUserManager.Stub { 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 @@ public class UserManagerService extends IUserManager.Stub { (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 @@ public class UserManagerService extends IUserManager.Stub { 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 @@ public class UserManagerService extends IUserManager.Stub { 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 @@ public class UserManagerService extends IUserManager.Stub { 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 @@ public class UserManagerService extends IUserManager.Stub { @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 46fde4b59d8b..60602337ba1a 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 @@ public class OneTimePermissionUserManager { 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 71554eee3127..5a05134bed81 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 @@ public class PermissionManagerService extends IPermissionManager.Stub { } @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 90842619c31e..009d155e96ef 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 @@ public class PermissionManagerServiceImpl implements PermissionManagerServiceInt } } - @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); @@ -3291,10 +3272,13 @@ public class PermissionManagerServiceImpl implements PermissionManagerServiceInt } else if (pkg.isSystemExt()) { permissions = systemConfig.getSystemExtPrivAppPermissions(pkg.getPackageName()); } else if (containingApexPackageName != null) { + final ApexManager apexManager = ApexManager.getInstance(); + final String apexName = apexManager.getApexModuleNameForPackageName( + containingApexPackageName); final Set<String> privAppPermissions = systemConfig.getPrivAppPermissions( pkg.getPackageName()); final Set<String> apexPermissions = systemConfig.getApexPrivAppPermissions( - containingApexPackageName, pkg.getPackageName()); + apexName, pkg.getPackageName()); if (privAppPermissions != null) { // TODO(andreionea): Remove check as soon as all apk-in-apex // permission allowlists are migrated. 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 3e28320a2130..3771f030aefa 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 @@ public interface PermissionManagerServiceInterface extends PermissionManagerInte 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 b3239486a75f..f255db4a9801 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 class ParsingPackageUtils { 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 @@ public class ParsingPackageUtils { 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 @@ public class ParsingPackageUtils { 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 e79148d52715..1ac373f074ec 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 class PhoneWindowManager implements WindowManagerPolicy { 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, @@ -1023,7 +1023,8 @@ public class PhoneWindowManager implements WindowManagerPolicy { break; } case SHORT_PRESS_POWER_LOCK_OR_SLEEP: { - if (keyguardOn()) { + if (mKeyguardDelegate == null || !mKeyguardDelegate.hasKeyguard() + || !mKeyguardDelegate.isSecure(mCurrentUserId) || keyguardOn()) { sleepDefaultDisplayFromPowerButton(eventTime, 0); } else { lockNow(null /*options*/); 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 000000000000..f3457f5a221b --- /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 990b21c211a3..c0ab65a3215c 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.PhraseSoundModel; 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 @@ public class SoundTriggerHalConcurrentCaptureHandler implements ISoundTriggerHal /** 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.KEYPHRASE: { - PhraseRecognitionEvent event = new PhraseRecognitionEvent(); - event.common.status = RecognitionStatus.ABORTED; - event.common.type = SoundModelType.KEYPHRASE; - model.callback.phraseRecognitionCallback(modelHandle, event); - } - break; + case SoundModelType.GENERIC: + model.callback.recognitionCallback(modelHandle, AidlUtil.newAbortEvent()); + 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 934b0e46ee95..fd8dee8416f6 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.Properties; 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 @@ class SoundTriggerModule implements IBinder.DeathRecipient, ISoundTriggerHal.Glo @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 @@ class SoundTriggerModule implements IBinder.DeathRecipient, ISoundTriggerHal.Glo 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 @@ class SoundTriggerModule implements IBinder.DeathRecipient, ISoundTriggerHal.Glo 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 @@ class SoundTriggerModule implements IBinder.DeathRecipient, ISoundTriggerHal.Glo 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 @@ class SoundTriggerModule implements IBinder.DeathRecipient, ISoundTriggerHal.Glo } 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 @@ class SoundTriggerModule implements IBinder.DeathRecipient, ISoundTriggerHal.Glo } } } + } 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 2e60f130bc4b..526dccb72e39 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 @@ public class StatsPullAtomService extends SystemService { 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 @@ public class StatsPullAtomService extends SystemService { } 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 20cd8f5c12f8..adca21676f9d 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 @@ public class TrustAgentWrapper { // 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 53a9244837ed..672458bef4a7 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.ITvInteractiveAppService; 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 @@ public class TvInteractiveAppManagerService extends SystemService { 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 @@ public class TvInteractiveAppManagerService extends SystemService { 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 @@ public class TvInteractiveAppManagerService extends SystemService { } // 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 @@ public class TvInteractiveAppManagerService extends SystemService { 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 @@ public class TvInteractiveAppManagerService extends SystemService { 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 @@ public class TvInteractiveAppManagerService extends SystemService { 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 @@ public class TvInteractiveAppManagerService extends SystemService { 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 @@ public class TvInteractiveAppManagerService extends SystemService { } @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 @@ public class TvInteractiveAppManagerService extends SystemService { } @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 @@ public class TvInteractiveAppManagerService extends SystemService { } boolean shouldBind = (!serviceState.mSessionTokens.isEmpty()) - || (serviceState.mPendingPrepare) || (!serviceState.mPendingAppLinkInfo.isEmpty()) || (!serviceState.mPendingAppLinkCommand.isEmpty()); @@ -1738,7 +1727,7 @@ public class TvInteractiveAppManagerService extends SystemService { 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 @@ public class TvInteractiveAppManagerService extends SystemService { 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 @@ public class TvInteractiveAppManagerService extends SystemService { } } - 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 @@ public class TvInteractiveAppManagerService extends SystemService { } @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 397acfac2812..b45c962811ad 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 @@ public final class TimingsTraceAndSlog extends TimingsTraceLog { @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 d4648a4f313c..11ddac6a9740 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.IBinder; 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 @@ public final class AccessibilityWindowsPopulator extends WindowInfosListener { mService = service; mAccessibilityController = accessibilityController; mHandler = new MyHandler(mService.mH.getLooper()); - - register(); } /** @@ -219,8 +218,10 @@ public final class AccessibilityWindowsPopulator extends WindowInfosListener { } 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 543e44cce8b6..8018d5652b1b 100644 --- a/services/core/java/com/android/server/wm/ActivityClientController.java +++ b/services/core/java/com/android/server/wm/ActivityClientController.java @@ -746,9 +746,11 @@ class ActivityClientController extends IActivityClientController.Stub { // 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.setPictureInPictureActions(r.pictureInPictureArgs.getActions()); + rootTask.setPictureInPictureAspectRatio( + r.pictureInPictureArgs.getAspectRatioFloat(), + r.pictureInPictureArgs.getExpandedAspectRatioFloat()); + rootTask.setPictureInPictureActions(r.pictureInPictureArgs.getActions(), + r.pictureInPictureArgs.getCloseAction()); } } } finally { @@ -828,7 +830,7 @@ class ActivityClientController extends IActivityClientController.Stub { 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 +838,7 @@ class ActivityClientController extends IActivityClientController.Stub { 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 a8dd856c2191..7f84f61a91ff 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 @@ class ActivityMetricsLogger { 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 @@ class ActivityMetricsLogger { } 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 @@ class ActivityMetricsLogger { @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 @@ class ActivityMetricsLogger { 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 @@ class ActivityMetricsLogger { 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 @@ class ActivityMetricsLogger { 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 @@ class ActivityMetricsLogger { /** 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 @@ class ActivityMetricsLogger { } } + 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 @@ class ActivityMetricsLogger { /** 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 883ce99d313d..4bef126ee2c8 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 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A 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)); } @@ -2915,9 +2915,7 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A */ boolean supportsPictureInPicture() { return mAtmService.mSupportsPictureInPicture && isActivityTypeStandardOrUndefined() - && info.supportsPictureInPicture() - && (mDisplayContent != null && mDisplayContent.mDwpcHelper.isWindowingModeSupported( - WINDOWING_MODE_PINNED)); + && info.supportsPictureInPicture(); } /** @@ -3015,6 +3013,14 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A return false; } + // Check to see if PiP is supported for the display this container is on. + if (mDisplayContent != null && !mDisplayContent.mDwpcHelper.isWindowingModeSupported( + WINDOWING_MODE_PINNED)) { + Slog.w(TAG, "Display " + mDisplayContent.getDisplayId() + + " doesn't support enter picture-in-picture mode. caller = " + caller); + return false; + } + boolean isCurrentAppLocked = mAtmService.getLockTaskModeState() != LOCK_TASK_MODE_NONE; final TaskDisplayArea taskDisplayArea = getDisplayArea(); @@ -5603,19 +5609,8 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A "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 7d2dfa071597..7abcc4b808a1 100644 --- a/services/core/java/com/android/server/wm/ActivityStarter.java +++ b/services/core/java/com/android/server/wm/ActivityStarter.java @@ -1716,9 +1716,10 @@ class ActivityStarter { // If we are not able to proceed, disassociate the activity from the task. Leaving an // activity in an incomplete state can lead to issues, such as performing operations // without a window container. - final Task rootTask = mStartActivity.getRootTask(); - if (rootTask != null) { + if (mStartActivity.getTask() != null) { mStartActivity.finishIfPossible("startActivity", true /* oomAdj */); + } else if (mStartActivity.getParent() != null) { + mStartActivity.getParent().removeChild(mStartActivity); } // Root task should also be detached from display and be removed if it's empty. @@ -2730,10 +2731,11 @@ class ActivityStarter { 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 b5312c4de437..8b6262f0fcca 100644 --- a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java +++ b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java @@ -3523,14 +3523,16 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub { } // 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(); + final RemoteAction closeAction = r.pictureInPictureArgs.getCloseAction(); mRootWindowContainer.moveActivityToPinnedRootTask(r, null /* launchIntoPipHostActivity */, "enterPictureInPictureMode"); final Task task = r.getTask(); task.setPictureInPictureAspectRatio(aspectRatio, expandedAspectRatio); - task.setPictureInPictureActions(actions); + task.setPictureInPictureActions(actions, closeAction); // Continue the pausing process after entering pip. if (task.getPausingActivity() == r) { diff --git a/services/core/java/com/android/server/wm/AsyncRotationController.java b/services/core/java/com/android/server/wm/AsyncRotationController.java index 220d9ec8febb..e79e77cee58b 100644 --- a/services/core/java/com/android/server/wm/AsyncRotationController.java +++ b/services/core/java/com/android/server/wm/AsyncRotationController.java @@ -144,7 +144,8 @@ class AsyncRotationController extends FadeAnimationController implements Consume // Legacy animation doesn't need to wait for the start transaction. if (mTransitionOp == OP_LEGACY) { mIsStartTransactionCommitted = true; - } else if (displayContent.mTransitionController.useShellTransitionsRotation()) { + } else if (displayContent.mTransitionController.useShellTransitionsRotation() + || displayContent.mTransitionController.isCollecting(displayContent)) { keepAppearanceInPreviousRotation(); } } 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 000000000000..2f39d6db385e --- /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 23f14a7b7a16..dbc01413e6fa 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.content.ComponentName; 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 @@ import com.android.internal.protolog.common.ProtoLog; 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 @@ class BackNavigationController { * 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 @@ class BackNavigationController { 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 @@ class BackNavigationController { 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 @@ class BackNavigationController { 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 @@ class BackNavigationController { 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 @@ class BackNavigationController { 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 @@ class BackNavigationController { 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 @@ class BackNavigationController { 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 @@ class BackNavigationController { 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 @@ class BackNavigationController { 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 07a0c372778b..87523f44d4b6 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.content.res.Configuration; 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 @@ import com.android.internal.protolog.common.ProtoLog; 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 @@ final class ContentRecorder { * 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 @@ final class ContentRecorder { 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 @@ final class ContentRecorder { 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()); - 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()); + 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; } - // TODO(206461622) Migrate to using the RootDisplayArea - mRecordedWindowContainer = wc.getDisplayContent(); final Point surfaceSize = fetchSurfaceSizeIfPresent(); if (surfaceSize == null) { @@ -296,6 +271,107 @@ final class ContentRecorder { } /** + * 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/DisplayArea.java b/services/core/java/com/android/server/wm/DisplayArea.java index 08681119a306..dfa3b743292e 100644 --- a/services/core/java/com/android/server/wm/DisplayArea.java +++ b/services/core/java/com/android/server/wm/DisplayArea.java @@ -662,7 +662,7 @@ public class DisplayArea<T extends WindowContainer> extends WindowContainer<T> { mDimmer.resetDimStates(); } - if (mDimmer.updateDims(getPendingTransaction(), mTmpDimBoundsRect)) { + if (mDimmer.updateDims(getSyncTransaction(), mTmpDimBoundsRect)) { scheduleAnimation(); } } diff --git a/services/core/java/com/android/server/wm/DisplayContent.java b/services/core/java/com/android/server/wm/DisplayContent.java index 59ba4e770b5d..f5ace6c78288 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.RESUMED_ACTIVITY; 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_WITH_CLASS_NAME 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 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp 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 ((pendingLayoutChanges & FINISH_LAYOUT_REDO_WALLPAPER) != 0) { - mWallpaperController.adjustWallpaperWindows(); - } + if (DEBUG_LAYOUT_REPEATS) surfacePlacer.debugLayoutRepeats("On entry to LockedInner", + pendingLayoutChanges); - 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_WALLPAPER) != 0) { + mWallpaperController.adjustWallpaperWindows(); + } - 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 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp // 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 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp // 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 4148d8b7d853..88d7dff4ff1a 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_APPLICATION_WINDOW; 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 android.window.DisplayAreaOrganizer.FEATURE_UNDEFINED; 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.os.UserHandle; 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.WindowManager.LayoutParams; 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 @@ public class DisplayPolicy { 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 @@ public class DisplayPolicy { 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 @@ public class DisplayPolicy { } }, - // 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 @@ public class DisplayPolicy { 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 @@ public class DisplayPolicy { 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 @@ public class DisplayPolicy { 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); - - 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()); + sTmpClientFrames); - if (!sTmpLastParentFrame.equals(pf)) { - windowFrames.setContentChanged(true); - } - - win.setFrame(); + win.setFrames(sTmpClientFrames); } WindowState getTopFullscreenOpaqueWindow() { @@ -1558,7 +1575,6 @@ public class DisplayPolicy { mStatusBarBackgroundWindows.clear(); mStatusBarColorCheckedBounds.setEmpty(); mStatusBarBackgroundCheckedBounds.setEmpty(); - mForceStatusBar = false; mAllowLockscreenWhenOn = false; mShowingDream = false; @@ -1599,9 +1615,6 @@ public class DisplayPolicy { && 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 @@ public class DisplayPolicy { } /** - * 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 @@ public class DisplayPolicy { 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 @@ public class DisplayPolicy { } mService.mPolicy.setAllowLockscreenWhenOn(getDisplayId(), mAllowLockscreenWhenOn); - return changes; } /** @@ -2441,6 +2406,18 @@ public class DisplayPolicy { 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 @@ public class DisplayPolicy { } } 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/EnsureActivitiesVisibleHelper.java b/services/core/java/com/android/server/wm/EnsureActivitiesVisibleHelper.java index aa5e20d9ec7f..7844bffb6247 100644 --- a/services/core/java/com/android/server/wm/EnsureActivitiesVisibleHelper.java +++ b/services/core/java/com/android/server/wm/EnsureActivitiesVisibleHelper.java @@ -108,8 +108,11 @@ class EnsureActivitiesVisibleHelper { && childTaskFragment.getTopNonFinishingActivity() != null) { childTaskFragment.updateActivityVisibilities(starting, configChanges, preserveWindows, notifyClients); + // The TaskFragment should fully occlude the activities below if the bounds + // equals to its parent task, unless it is translucent. mBehindFullyOccludedContainer |= - childTaskFragment.getBounds().equals(mTaskFragment.getBounds()); + (childTaskFragment.getBounds().equals(mTaskFragment.getBounds()) + && !childTaskFragment.isTranslucent(starting)); if (mAboveTop && mTop.getTaskFragment() == childTaskFragment) { mAboveTop = false; } diff --git a/services/core/java/com/android/server/wm/HighRefreshRateDenylist.java b/services/core/java/com/android/server/wm/HighRefreshRateDenylist.java index 5e8d795ce955..5d088d886b14 100644 --- a/services/core/java/com/android/server/wm/HighRefreshRateDenylist.java +++ b/services/core/java/com/android/server/wm/HighRefreshRateDenylist.java @@ -41,9 +41,6 @@ class HighRefreshRateDenylist { private final String[] mDefaultDenylist; private final Object mLock = new Object(); - private DeviceConfigInterface mDeviceConfig; - private OnPropertiesChangedListener mListener = new OnPropertiesChangedListener(); - static HighRefreshRateDenylist create(@NonNull Resources r) { return new HighRefreshRateDenylist(r, DeviceConfigInterface.REAL); } @@ -51,10 +48,9 @@ class HighRefreshRateDenylist { @VisibleForTesting HighRefreshRateDenylist(Resources r, DeviceConfigInterface deviceConfig) { mDefaultDenylist = r.getStringArray(R.array.config_highRefreshRateBlacklist); - mDeviceConfig = deviceConfig; - mDeviceConfig.addOnPropertiesChangedListener(DeviceConfig.NAMESPACE_DISPLAY_MANAGER, - BackgroundThread.getExecutor(), mListener); - final String property = mDeviceConfig.getProperty(DeviceConfig.NAMESPACE_DISPLAY_MANAGER, + deviceConfig.addOnPropertiesChangedListener(DeviceConfig.NAMESPACE_DISPLAY_MANAGER, + BackgroundThread.getExecutor(), new OnPropertiesChangedListener()); + final String property = deviceConfig.getProperty(DeviceConfig.NAMESPACE_DISPLAY_MANAGER, KEY_HIGH_REFRESH_RATE_BLACKLIST); updateDenylist(property); } @@ -95,14 +91,6 @@ class HighRefreshRateDenylist { } } - /** Used to prevent WmTests leaking issues. */ - @VisibleForTesting - void dispose() { - mDeviceConfig.removeOnPropertiesChangedListener(mListener); - mDeviceConfig = null; - mDenylistedPackages.clear(); - } - private class OnPropertiesChangedListener implements DeviceConfig.OnPropertiesChangedListener { public void onPropertiesChanged(@NonNull DeviceConfig.Properties properties) { if (properties.getKeyset().contains(KEY_HIGH_REFRESH_RATE_BLACKLIST)) { diff --git a/services/core/java/com/android/server/wm/ImeInsetsSourceProvider.java b/services/core/java/com/android/server/wm/ImeInsetsSourceProvider.java index 199517c441ad..0d4cfa3a8128 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 static com.android.server.wm.WindowManagerService.H.UPDATE_MULTI_WINDOW_S 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 @@ final class ImeInsetsSourceProvider extends WindowContainerInsetsSourceProvider } @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 3951c567e89c..9844cb5fe8f8 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 @@ class InsetsPolicy { // 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 047bf2f53b68..f3f08b202fed 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 @@ abstract class InsetsSourceProvider { 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 @@ abstract class InsetsSourceProvider { 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 @@ abstract class InsetsSourceProvider { * 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 @@ abstract class InsetsSourceProvider { 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 @@ abstract class InsetsSourceProvider { } } + 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 @@ abstract class InsetsSourceProvider { ? windowState.wouldBeVisibleIfPolicyIgnored() && windowState.isVisibleByPolicy() : mWindowContainer.isVisibleRequested(); setServerVisible(isServerVisible); - updateSourceFrame(); if (mControl != null) { boolean changed = false; final Point position = getWindowFrameSurfacePosition(); @@ -496,6 +493,7 @@ abstract class InsetsSourceProvider { @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 78608e2bf203..a19d72e37124 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 static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_IME; 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 @@ class InsetsStateController { } } - /** - * 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/LaunchParamsController.java b/services/core/java/com/android/server/wm/LaunchParamsController.java index 8e5d73f13dfb..7bd2a4a28e69 100644 --- a/services/core/java/com/android/server/wm/LaunchParamsController.java +++ b/services/core/java/com/android/server/wm/LaunchParamsController.java @@ -142,18 +142,6 @@ class LaunchParamsController { mService.deferWindowLayout(); try { - if (mTmpParams.mPreferredTaskDisplayArea != null - && task.getDisplayArea() != mTmpParams.mPreferredTaskDisplayArea) { - mService.mRootWindowContainer.moveRootTaskToTaskDisplayArea(task.getRootTaskId(), - mTmpParams.mPreferredTaskDisplayArea, true /* onTop */); - } - - if (mTmpParams.hasWindowingMode() && task.isRootTask() - && mTmpParams.mWindowingMode != task.getWindowingMode()) { - task.setWindowingMode(task.getDisplayArea().validateWindowingMode( - mTmpParams.mWindowingMode, activity, task)); - } - if (mTmpParams.mBounds.isEmpty()) { return false; } diff --git a/services/core/java/com/android/server/wm/MirrorActiveUids.java b/services/core/java/com/android/server/wm/MirrorActiveUids.java index 4e7f1d4cca18..b9aa9599babe 100644 --- a/services/core/java/com/android/server/wm/MirrorActiveUids.java +++ b/services/core/java/com/android/server/wm/MirrorActiveUids.java @@ -19,7 +19,7 @@ package com.android.server.wm; import static android.app.ActivityManager.PROCESS_STATE_NONEXISTENT; import android.app.ActivityManager.ProcessState; -import android.util.SparseArray; +import android.util.SparseIntArray; import java.io.PrintWriter; @@ -29,15 +29,14 @@ import java.io.PrintWriter; * adjustment) or getting state from window manager (background start check). */ class MirrorActiveUids { - private final SparseArray<UidRecord> mUidStates = new SparseArray<>(); + /** Uid -> process state. */ + private final SparseIntArray mUidStates = new SparseIntArray(); + + /** Uid -> number of non-app visible windows belong to the uid. */ + private final SparseIntArray mNumNonAppVisibleWindowMap = new SparseIntArray(); synchronized void onUidActive(int uid, int procState) { - UidRecord r = mUidStates.get(uid); - if (r == null) { - r = new UidRecord(); - mUidStates.put(uid, r); - } - r.mProcState = procState; + mUidStates.put(uid, procState); } synchronized void onUidInactive(int uid) { @@ -45,22 +44,28 @@ class MirrorActiveUids { } synchronized void onUidProcStateChanged(int uid, int procState) { - final UidRecord r = mUidStates.get(uid); - if (r != null) { - r.mProcState = procState; + final int index = mUidStates.indexOfKey(uid); + if (index >= 0) { + mUidStates.setValueAt(index, procState); } } synchronized @ProcessState int getUidState(int uid) { - final UidRecord r = mUidStates.get(uid); - return r != null ? r.mProcState : PROCESS_STATE_NONEXISTENT; + return mUidStates.get(uid, PROCESS_STATE_NONEXISTENT); } /** Called when the surface of non-application (exclude toast) window is shown or hidden. */ synchronized void onNonAppSurfaceVisibilityChanged(int uid, boolean visible) { - final UidRecord r = mUidStates.get(uid); - if (r != null) { - r.mNumNonAppVisibleWindow += visible ? 1 : -1; + final int index = mNumNonAppVisibleWindowMap.indexOfKey(uid); + if (index >= 0) { + final int num = mNumNonAppVisibleWindowMap.valueAt(index) + (visible ? 1 : -1); + if (num > 0) { + mNumNonAppVisibleWindowMap.setValueAt(index, num); + } else { + mNumNonAppVisibleWindowMap.removeAt(index); + } + } else if (visible) { + mNumNonAppVisibleWindowMap.append(uid, 1); } } @@ -70,23 +75,15 @@ class MirrorActiveUids { * {@link VisibleActivityProcessTracker}. */ synchronized boolean hasNonAppVisibleWindow(int uid) { - final UidRecord r = mUidStates.get(uid); - return r != null && r.mNumNonAppVisibleWindow > 0; + return mNumNonAppVisibleWindowMap.get(uid) > 0; } synchronized void dump(PrintWriter pw, String prefix) { - pw.print(prefix + "NumNonAppVisibleWindowByUid:["); - for (int i = mUidStates.size() - 1; i >= 0; i--) { - final UidRecord r = mUidStates.valueAt(i); - if (r.mNumNonAppVisibleWindow > 0) { - pw.print(" " + mUidStates.keyAt(i) + ":" + r.mNumNonAppVisibleWindow); - } + pw.print(prefix + "NumNonAppVisibleWindowUidMap:["); + for (int i = mNumNonAppVisibleWindowMap.size() - 1; i >= 0; i--) { + pw.print(" " + mNumNonAppVisibleWindowMap.keyAt(i) + ":" + + mNumNonAppVisibleWindowMap.valueAt(i)); } pw.println("]"); } - - private static final class UidRecord { - @ProcessState int mProcState; - int mNumNonAppVisibleWindow; - } } diff --git a/services/core/java/com/android/server/wm/PinnedTaskController.java b/services/core/java/com/android/server/wm/PinnedTaskController.java index 06e3a73940b4..43d077664fd5 100644 --- a/services/core/java/com/android/server/wm/PinnedTaskController.java +++ b/services/core/java/com/android/server/wm/PinnedTaskController.java @@ -92,6 +92,7 @@ class PinnedTaskController { // The set of actions and aspect-ratio for the that are currently allowed on the PiP activity private ArrayList<RemoteAction> mActions = new ArrayList<>(); + private RemoteAction mCloseAction; private float mAspectRatio = -1f; private float mExpandedAspectRatio = 0f; @@ -154,7 +155,7 @@ class PinnedTaskController { mPinnedTaskListener = listener; notifyImeVisibilityChanged(mIsImeShowing, mImeHeight); notifyMovementBoundsChanged(false /* fromImeAdjustment */); - notifyActionsChanged(mActions); + notifyActionsChanged(mActions, mCloseAction); } catch (RemoteException e) { Log.e(TAG, "Failed to register pinned task listener", e); } @@ -408,12 +409,13 @@ class PinnedTaskController { /** * Sets the current set of actions. */ - void setActions(List<RemoteAction> actions) { + void setActions(List<RemoteAction> actions, RemoteAction closeAction) { mActions.clear(); if (actions != null) { mActions.addAll(actions); } - notifyActionsChanged(mActions); + mCloseAction = closeAction; + notifyActionsChanged(mActions, closeAction); } /** @@ -450,10 +452,10 @@ class PinnedTaskController { /** * Notifies listeners that the PIP actions have changed. */ - private void notifyActionsChanged(List<RemoteAction> actions) { + private void notifyActionsChanged(List<RemoteAction> actions, RemoteAction closeAction) { if (mPinnedTaskListener != null) { try { - mPinnedTaskListener.onActionsChanged(new ParceledListSlice(actions)); + mPinnedTaskListener.onActionsChanged(new ParceledListSlice(actions), closeAction); } catch (RemoteException e) { Slog.e(TAG_WM, "Error delivering actions changed event.", e); } diff --git a/services/core/java/com/android/server/wm/Session.java b/services/core/java/com/android/server/wm/Session.java index 0c60919180fa..9ad25ac8876f 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 @@ class Session extends IWindowSession.Stub implements IBinder.DeathRecipient { 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 @@ class Session extends IWindowSession.Stub implements IBinder.DeathRecipient { @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 cd7ebe327c91..f3cefca10b06 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 android.view.WindowManager.TRANSIT_TO_FRONT; 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 @@ class Task extends TaskFragment { 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 @@ class Task extends TaskFragment { } 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; } @@ -3286,9 +3297,10 @@ class Task extends TaskFragment { mTmpDimBoundsRect.offsetTo(0, 0); } - updateShadowsRadius(isFocused(), getSyncTransaction()); + final SurfaceControl.Transaction t = getSyncTransaction(); + updateShadowsRadius(isFocused(), t); - if (mDimmer.updateDims(getPendingTransaction(), mTmpDimBoundsRect)) { + if (mDimmer.updateDims(t, mTmpDimBoundsRect)) { scheduleAnimation(); } @@ -3298,7 +3310,7 @@ class Task extends TaskFragment { final boolean show = isVisible() || isAnimating(TRANSITION | PARENTS | CHILDREN); if (mSurfaceControl != null) { if (show != mLastSurfaceShowing) { - getSyncTransaction().setVisibility(mSurfaceControl, show); + t.setVisibility(mSurfaceControl, show); } } mLastSurfaceShowing = show; @@ -3322,6 +3334,14 @@ class Task extends TaskFragment { } }); } + } 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); } @@ -6079,7 +6099,7 @@ class Task extends TaskFragment { /** * Sets the current picture-in-picture actions. */ - void setPictureInPictureActions(List<RemoteAction> actions) { + void setPictureInPictureActions(List<RemoteAction> actions, RemoteAction closeAction) { if (!mWmService.mAtmService.mSupportsPictureInPicture) { return; } @@ -6088,7 +6108,7 @@ class Task extends TaskFragment { return; } - getDisplayContent().getPinnedTaskController().setActions(actions); + getDisplayContent().getPinnedTaskController().setActions(actions, closeAction); } public DisplayInfo getDisplayInfo() { diff --git a/services/core/java/com/android/server/wm/TaskDisplayArea.java b/services/core/java/com/android/server/wm/TaskDisplayArea.java index 2f50b14968d5..7bb7870cea80 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 @@ final class TaskDisplayArea extends DisplayArea<WindowContainer> { } 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 @@ final class TaskDisplayArea extends DisplayArea<WindowContainer> { 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 597d29f5cd03..c0bc0191b16d 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.DISPLAY_ID; 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 @@ class TaskFragment extends WindowContainer<WindowContainer> { // 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 @@ class TaskFragment extends WindowContainer<WindowContainer> { if (!hasChild()) { return false; } - return isAnimating(TRANSITION | CHILDREN, WindowState.EXIT_ANIMATING_TYPES) - || inTransition(); + return isExitAnimationRunningSelfOrChild() || inTransition(); } @Override @@ -2427,7 +2425,7 @@ class TaskFragment extends WindowContainer<WindowContainer> { // Bounds need to be relative, as the dim layer is a child. final Rect dimBounds = getBounds(); dimBounds.offsetTo(0 /* newLeft */, 0 /* newTop */); - if (mDimmer.updateDims(getPendingTransaction(), dimBounds)) { + if (mDimmer.updateDims(getSyncTransaction(), dimBounds)) { scheduleAnimation(); } } diff --git a/services/core/java/com/android/server/wm/WindowContainer.java b/services/core/java/com/android/server/wm/WindowContainer.java index dab02dec5f7d..e7b4e834eb5a 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 @@ class WindowContainer<E extends WindowContainer> extends ConfigurationContainer< 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/WindowManagerConstants.java b/services/core/java/com/android/server/wm/WindowManagerConstants.java index bdbcd166dc0b..1931be4015c6 100644 --- a/services/core/java/com/android/server/wm/WindowManagerConstants.java +++ b/services/core/java/com/android/server/wm/WindowManagerConstants.java @@ -91,12 +91,6 @@ final class WindowManagerConstants { updateSystemGestureExcludedByPreQStickyImmersive(); } - @VisibleForTesting - void dispose() { - mDeviceConfig.removeOnPropertiesChangedListener(mListenerAndroid); - mDeviceConfig.removeOnPropertiesChangedListener(mListenerWindowManager); - } - private void onAndroidPropertiesChanged(DeviceConfig.Properties properties) { synchronized (mGlobalLock) { boolean updateSystemGestureExclusionLimit = false; diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java index 6718235e8982..43e84ae91118 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.REMOVE_CONTENT_MODE_UNDEFINED; 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.DisplayContent.IME_TARGET_LAYERING; 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 @@ public class WindowManagerService extends IWindowManager.Stub private final DisplayHashController mDisplayHashController; + volatile float mMaximumObscuringOpacityForTouch = + InputManager.DEFAULT_MAXIMUM_OBSCURING_OPACITY_FOR_TOUCH; + @VisibleForTesting final WindowContextListenerController mWindowContextListenerController = new WindowContextListenerController(); @@ -782,6 +783,8 @@ public class WindowManagerService extends IWindowManager.Stub 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 @@ public class WindowManagerService extends IWindowManager.Stub UserHandle.USER_ALL); resolver.registerContentObserver(mDisplaySettingsPathUri, false, this, UserHandle.USER_ALL); + resolver.registerContentObserver(mMaximumObscuringOpacityForTouchUri, false, this, + UserHandle.USER_ALL); } @Override @@ -849,6 +854,11 @@ public class WindowManagerService extends IWindowManager.Stub return; } + if (mMaximumObscuringOpacityForTouchUri.equals(uri)) { + updateMaximumObscuringOpacityForTouch(); + return; + } + @UpdateAnimationScaleMode final int mode; if (mWindowAnimationScaleUri.equals(uri)) { @@ -868,6 +878,14 @@ public class WindowManagerService extends IWindowManager.Stub 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 @@ public class WindowManagerService extends IWindowManager.Stub w.mGivenTouchableRegion.scale(w.mGlobalScale); } w.setDisplayLayoutNeeded(); + w.updateSourceFrame(w.getFrame()); mWindowPlacerLocked.performSurfacePlacement(); w.getDisplayContent().getInputMonitor().updateInputWindowsLw(true); @@ -2192,7 +2211,7 @@ public class WindowManagerService extends IWindowManager.Stub 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 @@ public class WindowManagerService extends IWindowManager.Stub 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 @@ public class WindowManagerService extends IWindowManager.Stub 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 @@ public class WindowManagerService extends IWindowManager.Stub } 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 @@ public class WindowManagerService extends IWindowManager.Stub 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 @@ public class WindowManagerService extends IWindowManager.Stub 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/WindowOrganizerController.java b/services/core/java/com/android/server/wm/WindowOrganizerController.java index d86201294235..044da3982e26 100644 --- a/services/core/java/com/android/server/wm/WindowOrganizerController.java +++ b/services/core/java/com/android/server/wm/WindowOrganizerController.java @@ -94,6 +94,7 @@ import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.Map; +import java.util.function.IntSupplier; /** * Server side implementation for the interface for organizing windows @@ -810,26 +811,8 @@ class WindowOrganizerController extends IWindowOrganizerController.Stub launchOpts.remove(WindowContainerTransaction.HierarchyOp.LAUNCH_KEY_TASK_ID); final SafeActivityOptions safeOptions = SafeActivityOptions.fromBundle(launchOpts, caller.mPid, caller.mUid); - final Integer[] starterResult = {null}; - // startActivityFromRecents should not be called in lock. - mService.mH.post(() -> { - try { - starterResult[0] = mService.mTaskSupervisor.startActivityFromRecents( - caller.mPid, caller.mUid, taskId, safeOptions); - } catch (Throwable t) { - starterResult[0] = ActivityManager.START_CANCELED; - Slog.w(TAG, t); - } - synchronized (mGlobalLock) { - mGlobalLock.notifyAll(); - } - }); - while (starterResult[0] == null) { - try { - mGlobalLock.wait(); - } catch (InterruptedException ignored) { - } - } + waitAsyncStart(() -> mService.mTaskSupervisor.startActivityFromRecents( + caller.mPid, caller.mUid, taskId, safeOptions)); break; } case HIERARCHY_OP_TYPE_PENDING_INTENT: { @@ -838,22 +821,22 @@ class WindowOrganizerController extends IWindowOrganizerController.Stub mService.mContext.getContentResolver()) : null; - Bundle options = null; + ActivityOptions activityOptions = null; if (hop.getPendingIntent().isActivity()) { // Set the context display id as preferred for this activity launches, so that // it can land on caller's display. Or just brought the task to front at the // display where it was on since it has higher preference. - ActivityOptions activityOptions = hop.getLaunchOptions() != null + activityOptions = hop.getLaunchOptions() != null ? new ActivityOptions(hop.getLaunchOptions()) : ActivityOptions.makeBasic(); activityOptions.setCallerDisplayId(DEFAULT_DISPLAY); - options = activityOptions.toBundle(); } - - mService.mAmInternal.sendIntentSender(hop.getPendingIntent().getTarget(), + final Bundle options = activityOptions != null ? activityOptions.toBundle() : null; + waitAsyncStart(() -> mService.mAmInternal.sendIntentSender( + hop.getPendingIntent().getTarget(), hop.getPendingIntent().getWhitelistToken(), 0 /* code */, hop.getActivityIntent(), resolvedType, null /* finishReceiver */, - null /* requiredPermission */, options); + null /* requiredPermission */, options)); break; } case HIERARCHY_OP_TYPE_START_SHORTCUT: { @@ -914,6 +897,31 @@ class WindowOrganizerController extends IWindowOrganizerController.Stub return effects; } + /** + * Post and wait for the result of the activity start to prevent potential deadlock against + * {@link WindowManagerGlobalLock}. + */ + private void waitAsyncStart(IntSupplier startActivity) { + final Integer[] starterResult = {null}; + mService.mH.post(() -> { + try { + starterResult[0] = startActivity.getAsInt(); + } catch (Throwable t) { + starterResult[0] = ActivityManager.START_CANCELED; + Slog.w(TAG, t); + } + synchronized (mGlobalLock) { + mGlobalLock.notifyAll(); + } + }); + while (starterResult[0] == null) { + try { + mGlobalLock.wait(); + } catch (InterruptedException ignored) { + } + } + } + private int sanitizeAndApplyHierarchyOp(WindowContainer container, WindowContainerTransaction.HierarchyOp hop) { final Task task = container.asTask(); diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java index db687f627bfa..bb7876734260 100644 --- a/services/core/java/com/android/server/wm/WindowState.java +++ b/services/core/java/com/android/server/wm/WindowState.java @@ -37,6 +37,9 @@ import static android.view.ViewTreeObserver.InternalInsetsInfo.TOUCHABLE_INSETS_ import static android.view.ViewTreeObserver.InternalInsetsInfo.TOUCHABLE_INSETS_FRAME; import static android.view.ViewTreeObserver.InternalInsetsInfo.TOUCHABLE_INSETS_REGION; import static android.view.ViewTreeObserver.InternalInsetsInfo.TOUCHABLE_INSETS_VISIBLE; +import static android.view.WindowCallbacks.RESIZE_MODE_DOCKED_DIVIDER; +import static android.view.WindowCallbacks.RESIZE_MODE_FREEFORM; +import static android.view.WindowCallbacks.RESIZE_MODE_INVALID; import static android.view.WindowInsets.Type.systemBars; import static android.view.WindowInsetsController.BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE; import static android.view.WindowLayout.UNSPECIFIED_LENGTH; @@ -98,8 +101,6 @@ import static android.view.WindowManager.LayoutParams.TYPE_TOAST; import static android.view.WindowManager.LayoutParams.TYPE_VOLUME_OVERLAY; import static android.view.WindowManager.LayoutParams.TYPE_WALLPAPER; import static android.view.WindowManager.LayoutParams.isSystemAlertWindowType; -import static android.view.WindowManagerGlobal.RELAYOUT_RES_DRAG_RESIZING_DOCKED; -import static android.view.WindowManagerGlobal.RELAYOUT_RES_DRAG_RESIZING_FREEFORM; import static android.view.WindowManagerGlobal.RELAYOUT_RES_FIRST_TIME; import static android.view.WindowManagerPolicyConstants.TYPE_LAYER_MULTIPLIER; import static android.view.WindowManagerPolicyConstants.TYPE_LAYER_OFFSET; @@ -134,6 +135,7 @@ import static com.android.server.wm.SurfaceAnimator.ANIMATION_TYPE_APP_TRANSITIO 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 +143,6 @@ import static com.android.server.wm.WindowManagerDebugConfig.DEBUG; 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 +369,8 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP 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 +861,7 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP /** * @see #setOnBackInvokedCallback(IOnBackInvokedCallback) */ + // TODO(b/224856664): Consolidate application and system callback into one. private IOnBackInvokedCallback mApplicationOnBackInvokedCallback; private IOnBackInvokedCallback mSystemOnBackInvokedCallback; @@ -1124,7 +1127,9 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP this, onBackInvokedCallback); if (priority >= 0) { mApplicationOnBackInvokedCallback = onBackInvokedCallback; + mSystemOnBackInvokedCallback = null; } else { + mApplicationOnBackInvokedCallback = null; mSystemOnBackInvokedCallback = onBackInvokedCallback; } } @@ -1393,15 +1398,19 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP } // 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; - - if (mRequestedWidth != mLastRequestedWidth || mRequestedHeight != mLastRequestedHeight) { + 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 + || !mTmpRect.equals(windowFrames.mParentFrame)) { mLastRequestedWidth = mRequestedWidth; mLastRequestedHeight = mRequestedHeight; windowFrames.setContentChanged(true); @@ -1430,16 +1439,6 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP 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 +1453,19 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP } } - // 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 +2619,7 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP 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 @@ -3936,17 +3944,34 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP true /* useLatestConfig */, false /* relayoutVisible */); final boolean syncRedraw = shouldSendRedrawForSync(); final boolean reportDraw = syncRedraw || drawPending; - final boolean forceRelayout = syncRedraw || reportOrientation || isDragResizeChanged(); + final boolean isDragResizeChanged = isDragResizeChanged(); + final boolean forceRelayout = syncRedraw || reportOrientation || isDragResizeChanged; final DisplayContent displayContent = getDisplayContent(); final boolean alwaysConsumeSystemBars = displayContent.getDisplayPolicy().areSystemBarsForcedShownLw(); final int displayId = displayContent.getDisplayId(); + if (isDragResizeChanged) { + setDragResizing(); + } + int resizeMode = RESIZE_MODE_INVALID; + if (isDragResizing()) { + switch (getResizeMode()) { + case DRAG_RESIZE_MODE_FREEFORM: + resizeMode = RESIZE_MODE_FREEFORM; + break; + case DRAG_RESIZE_MODE_DOCKED_DIVIDER: + resizeMode = RESIZE_MODE_DOCKED_DIVIDER; + break; + } + } + markRedrawForSyncReported(); try { mClient.resized(mClientWindowFrames, reportDraw, mLastReportedConfiguration, - forceRelayout, alwaysConsumeSystemBars, displayId); + forceRelayout, alwaysConsumeSystemBars, displayId, Integer.MAX_VALUE, + resizeMode); if (drawPending && reportOrientation && mOrientationChanging) { mOrientationChangeRedrawRequestTime = SystemClock.elapsedRealtime(); ProtoLog.v(WM_DEBUG_ORIENTATION, @@ -4977,6 +5002,15 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP 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 +5022,7 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP 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 +5115,7 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP @Override boolean handleCompleteDeferredRemoval() { - if (mRemoveOnExit && !isSelfAnimating(0 /* flags */, EXIT_ANIMATING_TYPES)) { + if (mRemoveOnExit && !isSelfAnimating(0 /* flags */, ANIMATION_TYPE_WINDOW_ANIMATION)) { mRemoveOnExit = false; removeImmediately(); } @@ -5201,15 +5235,6 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER); } - if (isDragResizeChanged()) { - setDragResizing(); - } - final boolean freeformResizing = isDragResizing() - && getResizeMode() == DRAG_RESIZE_MODE_FREEFORM; - final boolean dockedResizing = isDragResizing() - && getResizeMode() == DRAG_RESIZE_MODE_DOCKED_DIVIDER; - result |= freeformResizing ? RELAYOUT_RES_DRAG_RESIZING_FREEFORM : 0; - result |= dockedResizing ? RELAYOUT_RES_DRAG_RESIZING_DOCKED : 0; return result; } @@ -5247,6 +5272,12 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP if (mControllableInsetProvider != null) { return; } + if (mDisplayContent.inTransition()) { + // Skip because the animation is usually unnoticeable (e.g. covered by rotation + // animation) and the animation bounds could be inconsistent, such as depending + // on when the window applies its draw transaction with new rotation. + return; + } final DisplayInfo displayInfo = getDisplayInfo(); anim.initialize(mWindowFrames.mFrame.width(), mWindowFrames.mFrame.height(), @@ -5491,10 +5522,8 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP } float newHScale = mHScale * mGlobalScale * mWallpaperScale; float newVScale = mVScale * mGlobalScale * mWallpaperScale; - if (mLastHScale != newHScale || - mLastVScale != newVScale ) { - getPendingTransaction().setMatrix(getSurfaceControl(), - newHScale, 0, 0, newVScale); + if (mLastHScale != newHScale || mLastVScale != newVScale) { + getSyncTransaction().setMatrix(mSurfaceControl, newHScale, 0, 0, newVScale); mLastHScale = newHScale; mLastVScale = newVScale; } @@ -5914,7 +5943,7 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP // 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 +5967,7 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP 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 +6014,7 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP void immediatelyNotifyBlastSync() { prepareDrawHandlers(); - finishDrawing(null); + finishDrawing(null, Integer.MAX_VALUE); mWmService.mH.removeMessages(WINDOW_STATE_BLAST_SYNC_TIMEOUT, this); if (!useBLASTSync()) return; } @@ -6057,7 +6086,7 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP */ 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 8a3d84cbe9c6..07d0a45e9c40 100644 --- a/services/core/jni/gnss/MeasurementCorrections.cpp +++ b/services/core/jni/gnss/MeasurementCorrections.cpp @@ -44,6 +44,7 @@ using SingleSatCorrection_Aidl = 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_correctionsHasEnvironmentBearing; 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_correctionSatIsLosProb; 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 @@ void MeasurementCorrections_class_init_once(JNIEnv* env, jclass clazz) { 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 @@ void MeasurementCorrections_class_init_once(JNIEnv* env, jclass clazz) { 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 @@ jboolean MeasurementCorrectionsIface_V1_1::setCallback( 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 @@ MeasurementCorrectionsUtil::getSingleSatCorrection_1_0_withoutConstellation( 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 @@ MeasurementCorrectionsUtil::getSingleSatCorrection_1_0_withoutConstellation( .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 @@ SingleSatCorrection_Aidl MeasurementCorrectionsUtil::getSingleSatCorrection_Aidl 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_Aidl MeasurementCorrectionsUtil::getSingleSatCorrection_Aidl 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 @@ void MeasurementCorrectionsUtil::getSingleSatCorrectionList_1_0( 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 @@ void MeasurementCorrectionsUtil::getSingleSatCorrectionList_1_1( 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 @@ void MeasurementCorrectionsUtil::getSingleSatCorrectionList_Aidl( 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 @@ void MeasurementCorrectionsUtil::getSingleSatCorrectionList_Aidl( } } +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 a2e602714326..598ad48d6ac1 100644 --- a/services/core/jni/gnss/MeasurementCorrections.h +++ b/services/core/jni/gnss/MeasurementCorrections.h @@ -43,7 +43,7 @@ extern jmethodID method_correctionsHasEnvironmentBearing; 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_correctionSatIsLosProb; 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 @@ struct MeasurementCorrectionsUtil { 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 @@ void MeasurementCorrectionsUtil::getReflectingPlane(JNIEnv* env, jobject singleS 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 2f5ab0b31332..48c40523e9c2 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 @@ class ActiveAdmin { 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 200b120843cc..834f65fa9e97 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; @@ -30,6 +31,7 @@ import android.util.Slog; import com.android.server.SystemService; +import java.util.Collections; import java.util.List; /** @@ -138,6 +140,11 @@ abstract class BaseIDevicePolicyManager extends IDevicePolicyManager.Stub { return null; } + public void finalizeWorkProfileProvisioning( + UserHandle managedProfileUser, Account migratedAccount) { + + } + public void provisionFullyManagedDevice( FullyManagedDeviceProvisioningParams provisioningParams, String callerPackage) { } @@ -171,7 +178,7 @@ abstract class BaseIDevicePolicyManager extends IDevicePolicyManager.Stub { 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 +190,20 @@ abstract class BaseIDevicePolicyManager extends IDevicePolicyManager.Stub { 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; + } + + @Override + public List<UserHandle> getPolicyManagedProfiles(UserHandle userHandle) { + return Collections.emptyList(); + } } diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DeviceManagementResourcesProvider.java b/services/devicepolicy/java/com/android/server/devicepolicy/DeviceManagementResourcesProvider.java index e70c071183ce..bf78c67d5b57 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 @@ class DeviceManagementResourcesProvider { 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 @@ class DeviceManagementResourcesProvider { 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 @@ class DeviceManagementResourcesProvider { // 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 @@ class DeviceManagementResourcesProvider { /** * 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 @@ class DeviceManagementResourcesProvider { @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 @@ class DeviceManagementResourcesProvider { 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 @@ class DeviceManagementResourcesProvider { } 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 @@ class DeviceManagementResourcesProvider { /** * 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 @@ class DeviceManagementResourcesProvider { @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 3d40f48f244d..1052d1dead87 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.ACTION_COMPLIANCE_ACKNOWLEDG 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.DELEGATION_SECURITY_LOGGING; 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 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { + "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 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { 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 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { 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 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { 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 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { 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 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { 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 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { } @Override - public void markProfileOwnerOnOrganizationOwnedDevice(ComponentName who, int userId) { + public void setProfileOwnerOnOrganizationOwnedDevice(ComponentName who, int userId, + boolean isProfileOwnerOnOrganizationOwnedDevice) { if (!mHasFeature) { return; } @@ -14804,13 +14807,14 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { // 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 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { 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 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { + " 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 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { 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 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { 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 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { 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 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { if (provisioningParams.isOrganizationOwnedProvisioning()) { synchronized (getLockObject()) { - markProfileOwnerOnOrganizationOwnedDeviceUncheckedLocked(admin, userInfo.id); + setProfileOwnerOnOrganizationOwnedDeviceUncheckedLocked(admin, userInfo.id, + true); } } @@ -17808,6 +17817,35 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { } } + @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 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { } 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 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { 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 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { drawableId, drawableStyle, drawableSource)); } - private void sendDrawableUpdatedBroadcast(String[] drawableIds) { + private void sendDrawableUpdatedBroadcast(List<String> drawableIds) { sendResourceUpdatedBroadcast(EXTRA_RESOURCE_TYPE_DRAWABLE, drawableIds); } @@ -18729,12 +18762,12 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { 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 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { 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,36 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { 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; + }); + } + + @Override + public List<UserHandle> getPolicyManagedProfiles(@NonNull UserHandle user) { + Preconditions.checkCallAuthorization(hasCallingOrSelfPermission( + android.Manifest.permission.MANAGE_PROFILE_AND_DEVICE_OWNERS)); + + int userId = user.getIdentifier(); + return mInjector.binderWithCleanCallingIdentity(() -> { + List<UserInfo> userProfiles = mUserManager.getProfiles(userId); + List<UserHandle> result = new ArrayList<>(); + for (int i = 0; i < userProfiles.size(); i++) { + if (userProfiles.get(i).isManagedProfile() && hasProfileOwner(userId)) { + result.add(new UserHandle(userProfiles.get(i).id)); + } + } + return result; + }); + } } diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerServiceShellCommand.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerServiceShellCommand.java index e1d720ca25c8..1fa2f53bea17 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 @@ final class DevicePolicyManagerServiceShellCommand extends ShellCommand { 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 fe8f2235ed63..b0fdd723347f 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 @@ class Owners { } } - /** - * 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 8f81e930d0cd..7a9c41256d61 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 @@ class AndroidPackageTest : ParcelableComponentTest(AndroidPackage::class, Packag 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 3cab5ecd3de1..7714cf0ca094 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 f05658bf6b0b..e09668756f10 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 @@ public class AlarmManagerServiceTest { 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 053551309661..d44fb3bc2448 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 androidx.test.platform.app.InstrumentationRegistry.getInstrumentat 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.AppPermissionTracker.AppPermissionPolicy; 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.UidBatteryConsumer; 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 android.util.Pair; 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 @@ public final class BackgroundRestrictionTest { @Mock private MediaSessionManager mMediaSessionManager; @Mock private RoleManager mRoleManager; @Mock private TelephonyManager mTelephonyManager; + @Mock private IAppOpsService mIAppOpsService; private long mCurrentTimeMillis; @@ -563,6 +568,7 @@ public final class BackgroundRestrictionTest { DeviceConfigSession<Float> bgCurrentDrainBgRestrictedThreshold = null; DeviceConfigSession<Boolean> bgPromptFgsWithNotiToBgRestricted = null; DeviceConfigSession<Long> bgNotificationMinInterval = null; + DeviceConfigSession<Integer> bgBatteryExemptionTypes = null; mBgRestrictionController.addAppBackgroundRestrictionListener(listener); @@ -624,20 +630,29 @@ public final class BackgroundRestrictionTest { 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 @@ public final class BackgroundRestrictionTest { 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 @@ public final class BackgroundRestrictionTest { 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 @@ public final class BackgroundRestrictionTest { // 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 @@ public final class BackgroundRestrictionTest { 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 @@ public final class BackgroundRestrictionTest { 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 @@ public final class BackgroundRestrictionTest { 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 @@ public final class BackgroundRestrictionTest { 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 @@ public final class BackgroundRestrictionTest { 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 @@ public final class BackgroundRestrictionTest { closeIfNotNull(bgCurrentDrainBgRestrictedThreshold); closeIfNotNull(bgPromptFgsWithNotiToBgRestricted); closeIfNotNull(bgNotificationMinInterval); + closeIfNotNull(bgBatteryExemptionTypes); } } @@ -1247,14 +1263,15 @@ public final class BackgroundRestrictionTest { 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 @@ public final class BackgroundRestrictionTest { 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 @@ public final class BackgroundRestrictionTest { 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 @@ public final class BackgroundRestrictionTest { // 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 @@ public final class BackgroundRestrictionTest { 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 @@ public final class BackgroundRestrictionTest { // 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 @@ public final class BackgroundRestrictionTest { // 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 @@ public final class BackgroundRestrictionTest { // 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 @@ public final class BackgroundRestrictionTest { // 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 @@ public final class BackgroundRestrictionTest { 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 @@ public final class BackgroundRestrictionTest { } 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 @@ public final class BackgroundRestrictionTest { } 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 @@ public final class BackgroundRestrictionTest { 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 @@ public final class BackgroundRestrictionTest { 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 @@ public final class BackgroundRestrictionTest { 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 @@ public final class BackgroundRestrictionTest { 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 784f732ba3b1..8d6269c93764 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 @@ public class LocalDisplayAdapterTest { 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 @@ public class LocalDisplayAdapterTest { .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 6f503c7dd941..444db9128662 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 @@ package com.android.server.pm; 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.Intent; 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 @@ public final class BackgroundDexOptServiceUnitTest { 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 @@ public final class BackgroundDexOptServiceUnitTest { 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 @@ public final class BackgroundDexOptServiceUnitTest { 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 41d46f223f4b..534d0a1bc76f 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 com.android.dx.mockito.inline.extended.ExtendedMockito.mockitoSess 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 @@ public class AgentTest { .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/tare/ScribeTest.java b/services/tests/mockingservicestests/src/com/android/server/tare/ScribeTest.java index ab29e5903f02..c2cf2ff439ca 100644 --- a/services/tests/mockingservicestests/src/com/android/server/tare/ScribeTest.java +++ b/services/tests/mockingservicestests/src/com/android/server/tare/ScribeTest.java @@ -109,6 +109,7 @@ public class ScribeTest { long lastReclamationTime = System.currentTimeMillis(); long remainingConsumableNarcs = 2000L; long consumptionLimit = 500_000L; + when(mIrs.getConsumptionLimitLocked()).thenReturn(consumptionLimit); Ledger ledger = mScribeUnderTest.getLedgerLocked(TEST_USER_ID, TEST_PACKAGE); ledger.recordTransaction(new Ledger.Transaction(0, 1000L, 1, null, 2000, 0)); @@ -119,8 +120,13 @@ public class ScribeTest { mScribeUnderTest.setConsumptionLimitLocked(consumptionLimit); mScribeUnderTest.adjustRemainingConsumableNarcsLocked( remainingConsumableNarcs - consumptionLimit); - mScribeUnderTest.writeImmediatelyForTesting(); + assertEquals(lastReclamationTime, mScribeUnderTest.getLastReclamationTimeLocked()); + assertEquals(remainingConsumableNarcs, + mScribeUnderTest.getRemainingConsumableNarcsLocked()); + assertEquals(consumptionLimit, mScribeUnderTest.getSatiatedConsumptionLimitLocked()); + + mScribeUnderTest.writeImmediatelyForTesting(); mScribeUnderTest.loadFromDiskLocked(); assertEquals(lastReclamationTime, mScribeUnderTest.getLastReclamationTimeLocked()); 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 000000000000..52cd29cabb94 --- /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 152f3b3abd13..e3be3a792549 100644 --- a/services/tests/servicestests/Android.bp +++ b/services/tests/servicestests/Android.bp @@ -64,6 +64,7 @@ android_test { "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 1f016fb6f017..56c51507606f 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 com.android.internal.accessibility.AccessibilityShortcutController 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.InstrumentationRegistry; 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 @@ public class AccessibilityManagerServiceTest { 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 @@ public class AccessibilityManagerServiceTest { 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 @@ public class AccessibilityManagerServiceTest { @SmallTest @Test public void testOnSystemActionsChanged() throws Exception { - setupAccessibilityServiceConnection(); + setupAccessibilityServiceConnection(0); final AccessibilityUserState userState = mA11yms.mUserStates.get( mA11yms.getCurrentUserIdLocked()); @@ -376,7 +385,7 @@ public class AccessibilityManagerServiceTest { @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 @@ public class AccessibilityManagerServiceTest { 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 f3a0b7fa1ea7..0780d219dc80 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.any; 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.content.IntentFilter; 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 @@ public class FullScreenMagnificationControllerTest { FullScreenMagnificationController mFullScreenMagnificationController; + public DisplayManagerInternal mDisplayManagerInternalMock = mock(DisplayManagerInternal.class); + @Before public void setUp() { Looper looper = InstrumentationRegistry.getContext().getMainLooper(); @@ -125,6 +131,12 @@ public class FullScreenMagnificationControllerTest { 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 eab96c09a00a..c17347320f52 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 @@ public class BiometricSchedulerOperationTest { @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 @@ public class BiometricSchedulerOperationTest { 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 @@ public class BiometricSchedulerOperationTest { 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 @@ public class BiometricSchedulerOperationTest { 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 @@ public class BiometricSchedulerOperationTest { 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 @@ public class BiometricSchedulerOperationTest { 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 class BiometricSchedulerOperationTest { 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 class BiometricSchedulerOperationTest { 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 class BiometricSchedulerOperationTest { 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 @@ public class BiometricSchedulerOperationTest { 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 @@ public class BiometricSchedulerOperationTest { 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 @@ public class BiometricSchedulerOperationTest { 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 0fa2b41e8b32..45e3b4373266 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 @@ public class BiometricSchedulerTest { // 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 @@ public class BiometricSchedulerTest { 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 dc39b6d573db..5012335b533f 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 com.google.common.truth.Truth.assertThat; 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 android.platform.test.annotations.Presubmit; 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 @@ import java.util.List; 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 @@ public class SensorOverlaysTest { @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 @@ public class SensorOverlaysTest { 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 52eee9a55cc7..8391914a0bb6 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 @@ package com.android.server.biometrics.sensors; 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.BiometricContext; 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 @@ public class UserAwareBiometricSchedulerTest { 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 @@ public class UserAwareBiometricSchedulerTest { @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 @@ public class UserAwareBiometricSchedulerTest { 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 @@ public class UserAwareBiometricSchedulerTest { 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 @@ public class UserAwareBiometricSchedulerTest { 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 @@ public class UserAwareBiometricSchedulerTest { 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 @@ public class UserAwareBiometricSchedulerTest { 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 de0f038e8ec5..6c50ca35be79 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 @@ public class FingerprintAuthenticationClientTest { 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 @@ public class FingerprintAuthenticationClientTest { 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 @@ public class FingerprintAuthenticationClientTest { 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 5a96f5cca52a..f77eb0bcc59f 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 @@ public class FingerprintEnrollClientTest { 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 @@ public class FingerprintEnrollClientTest { 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 @@ public class FingerprintEnrollClientTest { 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 1ebcbe10fae6..89bd10fdcdc3 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.Description; 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 @@ import java.util.concurrent.TimeUnit; */ @SmallTest @Presubmit +@Ignore("b/225415867") public class DevicePolicyManagerTest extends DpmTestBase { private static final String TAG = DevicePolicyManagerTest.class.getSimpleName(); @@ -4260,14 +4262,11 @@ public class DevicePolicyManagerTest extends DpmTestBase { 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 @@ public class DevicePolicyManagerTest extends DpmTestBase { 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 @@ public class DevicePolicyManagerTest extends DpmTestBase { configureContextForAccess(mContext, false); assertExpectException(SecurityException.class, /* messageRegex= */ null, - () -> dpm.markProfileOwnerOnOrganizationOwnedDevice(admin2)); + () -> dpm.setProfileOwnerOnOrganizationOwnedDevice(admin2, true)); } @Test @@ -6680,7 +6676,7 @@ public class DevicePolicyManagerTest extends DpmTestBase { configureContextForAccess(mContext, false); assertExpectException(SecurityException.class, /* messageRegex= */ null, - () -> dpm.markProfileOwnerOnOrganizationOwnedDevice(admin1)); + () -> dpm.setProfileOwnerOnOrganizationOwnedDevice(admin1, true)); } @Test @@ -6715,7 +6711,7 @@ public class DevicePolicyManagerTest extends DpmTestBase { 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 @@ public class DevicePolicyManagerTest extends DpmTestBase { 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 000000000000..26a83a23de33 --- /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 3cb5d5f92810..ce322f7cb6e6 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 static org.testng.Assert.assertThrows; 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.permission.PermissionManager; 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 @@ public class CrossProfileAppsServiceImplTest { FEATURE_ID, ACTIVITY_COMPONENT, UserHandle.of(PRIMARY_USER).getIdentifier(), - true)); + true, + /* targetTask */ null, + /* options */ null)); verify(mActivityTaskManagerInternal, never()) .startActivityAsUser( @@ -265,7 +269,9 @@ public class CrossProfileAppsServiceImplTest { FEATURE_ID, ACTIVITY_COMPONENT, UserHandle.of(PRIMARY_USER).getIdentifier(), - false)); + false, + /* targetTask */ null, + /* options */ null)); verify(mActivityTaskManagerInternal, never()) .startActivityAsUser( @@ -292,7 +298,9 @@ public class CrossProfileAppsServiceImplTest { 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 @@ public class CrossProfileAppsServiceImplTest { 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 @@ public class CrossProfileAppsServiceImplTest { 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 @@ public class CrossProfileAppsServiceImplTest { 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 @@ public class CrossProfileAppsServiceImplTest { 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 @@ public class CrossProfileAppsServiceImplTest { 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 @@ public class CrossProfileAppsServiceImplTest { 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 @@ public class CrossProfileAppsServiceImplTest { 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 @@ public class CrossProfileAppsServiceImplTest { FEATURE_ID, ACTIVITY_COMPONENT, UserHandle.of(SECONDARY_USER).getIdentifier(), - true)); + true, + /* targetTask */ null, + /* options */ null)); verify(mActivityTaskManagerInternal, never()) .startActivityAsUser( @@ -540,7 +564,9 @@ public class CrossProfileAppsServiceImplTest { FEATURE_ID, ACTIVITY_COMPONENT, UserHandle.of(SECONDARY_USER).getIdentifier(), - false)); + false, + /* targetTask */ null, + /* options */ null)); verify(mActivityTaskManagerInternal, never()) .startActivityAsUser( @@ -564,7 +590,9 @@ public class CrossProfileAppsServiceImplTest { FEATURE_ID, ACTIVITY_COMPONENT, UserHandle.of(PRIMARY_USER).getIdentifier(), - true); + true, + /* targetTask */ null, + /* options */ null); verify(mActivityTaskManagerInternal) .startActivityAsUser( @@ -578,6 +606,44 @@ public class CrossProfileAppsServiceImplTest { 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 99edecfeed30..c78678431dac 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.app.Person; 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 @@ public class ShortcutManagerTest2 extends BaseShortcutManagerTest { .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 @@ public class ShortcutManagerTest2 extends BaseShortcutManagerTest { 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 @@ public class ShortcutManagerTest2 extends BaseShortcutManagerTest { .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 @@ public class ShortcutManagerTest2 extends BaseShortcutManagerTest { 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 c7b5547170d0..06b711251c0f 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 @@ public final class UserManagerTest { 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 @@ public final class UserManagerTest { @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 final class UserManagerTest { 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 0eba6a335d00..0187e34cbc5f 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 @@ public class SoundTriggerMiddlewareImplTest { // 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 @@ public class SoundTriggerMiddlewareImplTest { // 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 d76a1de1b1b0..83139b02430a 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 class StatusBarManagerServiceTest { 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 31be33e98363..fd1536c5c0f1 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.ENABLED_FIELD_NUMBER; 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 @@ public class ZenModeHelperTest extends UiServiceTestCase { } @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 d4d8b86850c6..7689e08bc3f3 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 @@ public class ActivityMetricsLaunchObserverTests extends WindowTestsBase { 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 @@ public class ActivityMetricsLaunchObserverTests extends WindowTestsBase { @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/ActivityRecordTests.java b/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java index f8e15041f8f4..f9d4dffd4643 100644 --- a/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java @@ -16,6 +16,8 @@ package com.android.server.wm; +import static android.app.AppOpsManager.MODE_ALLOWED; +import static android.app.AppOpsManager.OP_PICTURE_IN_PICTURE; import static android.app.TaskInfo.CAMERA_COMPAT_CONTROL_DISMISSED; import static android.app.TaskInfo.CAMERA_COMPAT_CONTROL_HIDDEN; import static android.app.TaskInfo.CAMERA_COMPAT_CONTROL_TREATMENT_APPLIED; @@ -110,6 +112,7 @@ import static org.mockito.Mockito.clearInvocations; import static org.mockito.Mockito.never; import android.app.ActivityOptions; +import android.app.AppOpsManager; import android.app.ICompatCameraControlCallback; import android.app.PictureInPictureParams; import android.app.servertransaction.ActivityConfigurationChangeItem; @@ -2184,17 +2187,11 @@ public class ActivityRecordTests extends WindowTestsBase { @Test public void testSupportsPictureInPicture() { - final Task task = new TaskBuilder(mSupervisor) - .setDisplay(mDisplayContent).build(); final ActivityRecord activity = new ActivityBuilder(mAtm) - .setTask(task) + .setCreateTask(true) .setResizeMode(ActivityInfo.RESIZE_MODE_UNRESIZEABLE) .setActivityFlags(FLAG_SUPPORTS_PICTURE_IN_PICTURE) .build(); - spyOn(mDisplayContent); - spyOn(mDisplayContent.mDwpcHelper); - doReturn(true).when(mDisplayContent.mDwpcHelper).isWindowingModeSupported( - WINDOWING_MODE_PINNED); // Device not supports PIP mAtm.mSupportsPictureInPicture = false; @@ -2207,15 +2204,28 @@ public class ActivityRecordTests extends WindowTestsBase { // Activity not supports PIP activity.info.flags &= ~FLAG_SUPPORTS_PICTURE_IN_PICTURE; assertFalse(activity.supportsPictureInPicture()); + } - // Activity supports PIP - activity.info.flags |= FLAG_SUPPORTS_PICTURE_IN_PICTURE; - assertTrue(activity.supportsPictureInPicture()); + @Test + public void testCheckEnterPictureInPictureState_displayNotSupportedPip() { + final Task task = new TaskBuilder(mSupervisor) + .setDisplay(mDisplayContent).build(); + final ActivityRecord activity = new ActivityBuilder(mAtm) + .setTask(task) + .setResizeMode(ActivityInfo.RESIZE_MODE_UNRESIZEABLE) + .setActivityFlags(FLAG_SUPPORTS_PICTURE_IN_PICTURE) + .build(); + mAtm.mSupportsPictureInPicture = true; + AppOpsManager appOpsManager = mAtm.getAppOpsManager(); + doReturn(MODE_ALLOWED).when(appOpsManager).checkOpNoThrow(eq(OP_PICTURE_IN_PICTURE), + anyInt(), any()); + doReturn(false).when(mAtm).shouldDisableNonVrUiLocked(); - // Display not supports PIP + spyOn(mDisplayContent.mDwpcHelper); doReturn(false).when(mDisplayContent.mDwpcHelper).isWindowingModeSupported( WINDOWING_MODE_PINNED); - assertFalse(activity.supportsPictureInPicture()); + + assertFalse(activity.checkEnterPictureInPictureState("TEST", false /* beforeStopping */)); } @Test 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 f9aa4b17bc2c..9902e83c3648 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 @@ public class ActivityStarterTests extends WindowTestsBase { 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 c21a5b6ff7ea..92550a3107d5 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 static org.mockito.Mockito.when; 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 @@ import org.junit.runner.RunWith; 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 @@ public class BackNavigationControllerTests extends WindowTestsBase { Task taskA = createTask(mDefaultDisplay); createActivityRecord(taskA); Task task = createTopTaskWithActivity(); + registerSystemOnBackInvokedCallback(); + BackNavigationInfo backNavigationInfo = mBackNavigationController.startBackNavigation(task, new StubTransaction()); assertThat(backNavigationInfo).isNotNull(); @@ -75,6 +84,8 @@ public class BackNavigationControllerTests extends WindowTestsBase { 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 class BackNavigationControllerTests extends WindowTestsBase { 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 @@ public class BackNavigationControllerTests extends WindowTestsBase { 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 @@ public class BackNavigationControllerTests extends WindowTestsBase { 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 50eefa066a45..c5117bb83976 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 @@ package com.android.server.wm; 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.hardware.display.VirtualDisplay; 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 @@ import org.junit.runner.RunWith; @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 @@ public class ContentRecorderTests extends WindowTestsBase { 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,37 +128,79 @@ public class ContentRecorderTests extends WindowTestsBase { @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_wasPaused() { - mContentRecorder.setContentRecordingSession(mDefaultSession); + public void testUpdateRecording_display_noWindowContainer() { + doReturn(null).when( + mWm.mWindowContextListenerController).getContainer(any()); + mContentRecorder.setContentRecordingSession(mDisplaySession); mContentRecorder.updateRecording(); + assertThat(mContentRecorder.isCurrentlyRecording()).isFalse(); + } - mContentRecorder.pauseRecording(); + @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_wasStopped() { - mContentRecorder.setContentRecordingSession(mDefaultSession); + 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. + } - mContentRecorder.remove(); + @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(mDisplaySession); + mContentRecorder.updateRecording(); + + mContentRecorder.pauseRecording(); + mContentRecorder.updateRecording(); + assertThat(mContentRecorder.isCurrentlyRecording()).isTrue(); } @Test @@ -146,7 +214,7 @@ public class ContentRecorderTests extends WindowTestsBase { @Test public void testOnConfigurationChanged_resizesSurface() { - mContentRecorder.setContentRecordingSession(mDefaultSession); + mContentRecorder.setContentRecordingSession(mDisplaySession); mContentRecorder.updateRecording(); mContentRecorder.onConfigurationChanged(ORIENTATION_PORTRAIT); @@ -158,7 +226,7 @@ public class ContentRecorderTests extends WindowTestsBase { @Test public void testPauseRecording_pausesRecording() { - mContentRecorder.setContentRecordingSession(mDefaultSession); + mContentRecorder.setContentRecordingSession(mDisplaySession); mContentRecorder.updateRecording(); mContentRecorder.pauseRecording(); @@ -173,7 +241,7 @@ public class ContentRecorderTests extends WindowTestsBase { @Test public void testRemove_stopsRecording() { - mContentRecorder.setContentRecordingSession(mDefaultSession); + mContentRecorder.setContentRecordingSession(mDisplaySession); mContentRecorder.updateRecording(); mContentRecorder.remove(); @@ -188,8 +256,9 @@ public class ContentRecorderTests extends WindowTestsBase { @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 @@ public class ContentRecorderTests extends WindowTestsBase { 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 @@ public class ContentRecorderTests extends WindowTestsBase { } /** + * 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 @@ public class ContentRecorderTests extends WindowTestsBase { 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 db22757cc4fe..45ae81a71c44 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 @@ public class DisplayPolicyLayoutTests extends DisplayPolicyTestsBase { win.getFrame().set(0, 0, 500, 100); addWindow(win); + win.updateSourceFrame(win.getFrame()); InsetsStateController controller = mDisplayContent.getInsetsStateController(); controller.onPostLayout(); @@ -185,6 +186,7 @@ public class DisplayPolicyLayoutTests extends DisplayPolicyTestsBase { 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/HighRefreshRateDenylistTest.java b/services/tests/wmtests/src/com/android/server/wm/HighRefreshRateDenylistTest.java index dfc2e35ffedf..38ab683f81fe 100644 --- a/services/tests/wmtests/src/com/android/server/wm/HighRefreshRateDenylistTest.java +++ b/services/tests/wmtests/src/com/android/server/wm/HighRefreshRateDenylistTest.java @@ -33,7 +33,6 @@ import com.android.internal.R; import com.android.internal.util.Preconditions; import com.android.server.testutils.FakeDeviceConfigInterface; -import org.junit.After; import org.junit.Test; import java.util.concurrent.Executor; @@ -51,11 +50,6 @@ public class HighRefreshRateDenylistTest { private HighRefreshRateDenylist mDenylist; - @After - public void tearDown() { - mDenylist.dispose(); - } - @Test public void testDefaultDenylist() { final Resources r = createResources(APP1, APP2); 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 90a6918644fa..6d022262b720 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 @@ public class InsetsStateControllerTest extends WindowTestsBase { 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/LaunchParamsControllerTests.java b/services/tests/wmtests/src/com/android/server/wm/LaunchParamsControllerTests.java index 0c2de5c6031b..5265b442c968 100644 --- a/services/tests/wmtests/src/com/android/server/wm/LaunchParamsControllerTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/LaunchParamsControllerTests.java @@ -23,9 +23,7 @@ import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED; import static android.view.Display.INVALID_DISPLAY; import static com.android.dx.mockito.inline.extended.ExtendedMockito.any; -import static com.android.dx.mockito.inline.extended.ExtendedMockito.anyBoolean; import static com.android.dx.mockito.inline.extended.ExtendedMockito.anyInt; -import static com.android.dx.mockito.inline.extended.ExtendedMockito.doNothing; import static com.android.dx.mockito.inline.extended.ExtendedMockito.eq; import static com.android.dx.mockito.inline.extended.ExtendedMockito.mock; import static com.android.dx.mockito.inline.extended.ExtendedMockito.never; @@ -279,51 +277,6 @@ public class LaunchParamsControllerTests extends WindowTestsBase { } /** - * Ensures that {@link LaunchParamsModifier} requests specifying display id during - * layout are honored. - */ - @Test - public void testLayoutTaskPreferredDisplayChange() { - final LaunchParams params = new LaunchParams(); - final TestDisplayContent display = createNewDisplayContent(); - final TaskDisplayArea preferredTaskDisplayArea = display.getDefaultTaskDisplayArea(); - params.mPreferredTaskDisplayArea = preferredTaskDisplayArea; - final InstrumentedPositioner positioner = new InstrumentedPositioner(RESULT_DONE, params); - final Task task = new TaskBuilder(mAtm.mTaskSupervisor).build(); - - mController.registerModifier(positioner); - - doNothing().when(mRootWindowContainer).moveRootTaskToTaskDisplayArea(anyInt(), any(), - anyBoolean()); - mController.layoutTask(task, null /* windowLayout */); - verify(mRootWindowContainer, times(1)).moveRootTaskToTaskDisplayArea( - eq(task.getRootTaskId()), eq(preferredTaskDisplayArea), anyBoolean()); - } - - /** - * Ensures that {@link LaunchParamsModifier} requests specifying windowingMode during - * layout are honored. - */ - @Test - public void testLayoutTaskWindowingModeChange() { - final LaunchParams params = new LaunchParams(); - final int windowingMode = WINDOWING_MODE_FREEFORM; - params.mWindowingMode = windowingMode; - final InstrumentedPositioner positioner = new InstrumentedPositioner(RESULT_DONE, params); - final Task task = new TaskBuilder(mAtm.mTaskSupervisor).build(); - - mController.registerModifier(positioner); - - final int beforeWindowMode = task.getRootTask().getWindowingMode(); - assertNotEquals(windowingMode, beforeWindowMode); - - mController.layoutTask(task, null /* windowLayout */); - - final int afterWindowMode = task.getRootTask().getWindowingMode(); - assertEquals(windowingMode, afterWindowMode); - } - - /** * Ensures that {@link LaunchParamsModifier} doesn't alter non-root tasks' windowingMode. */ @Test @@ -355,10 +308,10 @@ public class LaunchParamsControllerTests extends WindowTestsBase { final Rect expected = new Rect(10, 20, 30, 40); final LaunchParams params = new LaunchParams(); - params.mWindowingMode = WINDOWING_MODE_FREEFORM; params.mBounds.set(expected); final InstrumentedPositioner positioner = new InstrumentedPositioner(RESULT_DONE, params); - final Task task = new TaskBuilder(mAtm.mTaskSupervisor).build(); + final Task task = new TaskBuilder(mAtm.mTaskSupervisor) + .setWindowingMode(WINDOWING_MODE_FREEFORM).build(); mController.registerModifier(positioner); @@ -380,10 +333,10 @@ public class LaunchParamsControllerTests extends WindowTestsBase { final Rect expected = new Rect(10, 20, 30, 40); final LaunchParams params = new LaunchParams(); - params.mWindowingMode = WINDOWING_MODE_MULTI_WINDOW; params.mBounds.set(expected); final InstrumentedPositioner positioner = new InstrumentedPositioner(RESULT_DONE, params); - final Task task = new TaskBuilder(mAtm.mTaskSupervisor).build(); + final Task task = new TaskBuilder(mAtm.mTaskSupervisor) + .setWindowingMode(WINDOWING_MODE_MULTI_WINDOW).build(); mController.registerModifier(positioner); diff --git a/services/tests/wmtests/src/com/android/server/wm/RootWindowContainerTests.java b/services/tests/wmtests/src/com/android/server/wm/RootWindowContainerTests.java index 99ba3b806d61..762c08f99d94 100644 --- a/services/tests/wmtests/src/com/android/server/wm/RootWindowContainerTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/RootWindowContainerTests.java @@ -20,6 +20,7 @@ import static android.app.KeyguardManager.ACTION_CONFIRM_DEVICE_CREDENTIAL_WITH_ import static android.app.WindowConfiguration.ACTIVITY_TYPE_HOME; import static android.app.WindowConfiguration.ACTIVITY_TYPE_RECENTS; import static android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD; +import static android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM; import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN; import static android.app.WindowConfiguration.WINDOWING_MODE_MULTI_WINDOW; import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED; @@ -945,14 +946,16 @@ public class RootWindowContainerTests extends WindowTestsBase { mWm, "TDA", FEATURE_VENDOR_FIRST); display.addChild(taskDisplayArea, POSITION_BOTTOM); - // Making sure getting the root task from the preferred TDA + // Making sure getting the root task from the preferred TDA and the preferred windowing mode LaunchParamsController.LaunchParams launchParams = new LaunchParamsController.LaunchParams(); launchParams.mPreferredTaskDisplayArea = taskDisplayArea; + launchParams.mWindowingMode = WINDOWING_MODE_FREEFORM; Task root = mRootWindowContainer.getOrCreateRootTask(null /* r */, null /* options */, null /* candidateTask */, null /* sourceTask */, true /* onTop */, launchParams, 0 /* launchParams */); assertEquals(taskDisplayArea, root.getTaskDisplayArea()); + assertEquals(WINDOWING_MODE_FREEFORM, root.getWindowingMode()); // Making sure still getting the root task from the preferred TDA when passing in a // launching activity. @@ -961,6 +964,7 @@ public class RootWindowContainerTests extends WindowTestsBase { null /* candidateTask */, null /* sourceTask */, true /* onTop */, launchParams, 0 /* launchParams */); assertEquals(taskDisplayArea, root.getTaskDisplayArea()); + assertEquals(WINDOWING_MODE_FREEFORM, root.getWindowingMode()); } @Test diff --git a/services/tests/wmtests/src/com/android/server/wm/SystemServicesTestRule.java b/services/tests/wmtests/src/com/android/server/wm/SystemServicesTestRule.java index f999e4978420..ce861595535c 100644 --- a/services/tests/wmtests/src/com/android/server/wm/SystemServicesTestRule.java +++ b/services/tests/wmtests/src/com/android/server/wm/SystemServicesTestRule.java @@ -18,6 +18,7 @@ package com.android.server.wm; import static android.app.WindowConfiguration.ACTIVITY_TYPE_HOME; import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN; +import static android.provider.DeviceConfig.NAMESPACE_CONSTRAIN_DISPLAY_APIS; import static android.testing.DexmakerShareClassLoaderRule.runWithDexmakerShareClassLoader; import static android.view.Display.DEFAULT_DISPLAY; @@ -27,6 +28,7 @@ import static com.android.dx.mockito.inline.extended.ExtendedMockito.any; import static com.android.dx.mockito.inline.extended.ExtendedMockito.anyBoolean; import static com.android.dx.mockito.inline.extended.ExtendedMockito.anyInt; import static com.android.dx.mockito.inline.extended.ExtendedMockito.anyString; +import static com.android.dx.mockito.inline.extended.ExtendedMockito.doAnswer; import static com.android.dx.mockito.inline.extended.ExtendedMockito.doNothing; import static com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn; import static com.android.dx.mockito.inline.extended.ExtendedMockito.eq; @@ -36,6 +38,9 @@ import static com.android.dx.mockito.inline.extended.ExtendedMockito.nullable; import static com.android.dx.mockito.inline.extended.ExtendedMockito.spy; import static com.android.dx.mockito.inline.extended.ExtendedMockito.spyOn; +import static org.mockito.Mockito.CALLS_REAL_METHODS; +import static org.mockito.Mockito.withSettings; + import android.app.ActivityManagerInternal; import android.app.AppOpsManager; import android.app.usage.UsageStatsManagerInternal; @@ -57,6 +62,7 @@ import android.os.PowerManagerInternal; import android.os.PowerSaveState; import android.os.StrictMode; import android.os.UserHandle; +import android.provider.DeviceConfig; import android.util.Log; import android.view.InputChannel; import android.view.Surface; @@ -83,10 +89,12 @@ import com.android.server.uri.UriGrantsManagerInternal; import org.junit.rules.TestRule; import org.junit.runner.Description; import org.junit.runners.model.Statement; +import org.mockito.MockSettings; import org.mockito.Mockito; import org.mockito.quality.Strictness; import java.io.File; +import java.util.ArrayList; import java.util.concurrent.atomic.AtomicBoolean; import java.util.function.Supplier; @@ -106,6 +114,13 @@ public class SystemServicesTestRule implements TestRule { .getSystemService(PowerManager.class).newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, TAG); private PowerManager.WakeLock mStubbedWakeLock; + /** + * The captured listeners will be unregistered in {@link #tearDown()} to avoid keeping static + * references of test instances from DeviceConfig. + */ + private final ArrayList<DeviceConfig.OnPropertiesChangedListener> mDeviceConfigListeners = + new ArrayList<>(); + private Description mDescription; private Context mContext; private StaticMockitoSession mMockitoSession; @@ -141,20 +156,29 @@ public class SystemServicesTestRule implements TestRule { Log.e("SystemServicesTestRule", "Suppressed: ", throwable); t.addSuppressed(throwable); } - throw t; + throwable = t; } - if (throwable != null) throw throwable; } + if (throwable != null) throw throwable; } }; } private void setUp() { + // Use stubOnly() to reduce memory usage if it doesn't need verification. + final MockSettings spyStubOnly = withSettings().stubOnly() + .defaultAnswer(CALLS_REAL_METHODS); + final MockSettings mockStubOnly = withSettings().stubOnly(); + // Return mocked services: LocalServices.getService + // Avoid real operation: SurfaceControl.mirrorSurface + // Avoid leakage: DeviceConfig.addOnPropertiesChangedListener, LockGuard.installLock + // Watchdog.getInstance/addMonitor mMockitoSession = mockitoSession() - .spyStatic(LocalServices.class) - .spyStatic(SurfaceControl.class) - .mockStatic(LockGuard.class) - .mockStatic(Watchdog.class) + .mockStatic(LocalServices.class, spyStubOnly) + .mockStatic(DeviceConfig.class, spyStubOnly) + .mockStatic(SurfaceControl.class, mockStubOnly) + .mockStatic(LockGuard.class, mockStubOnly) + .mockStatic(Watchdog.class, mockStubOnly) .strictness(Strictness.LENIENT) .startMocking(); @@ -166,6 +190,16 @@ public class SystemServicesTestRule implements TestRule { private void setUpSystemCore() { doReturn(mock(Watchdog.class)).when(Watchdog::getInstance); + doAnswer(invocation -> { + // Exclude CONSTRAIN_DISPLAY_APIS because ActivityRecord#sConstrainDisplayApisConfig + // only registers once and it doesn't reference to outside. + if (!NAMESPACE_CONSTRAIN_DISPLAY_APIS.equals(invocation.getArgument(0))) { + mDeviceConfigListeners.add(invocation.getArgument(2)); + } + // SizeCompatTests uses setNeverConstrainDisplayApisFlag, and ActivityRecordTests + // uses splash_screen_exception_list. So still execute real registration. + return invocation.callRealMethod(); + }).when(() -> DeviceConfig.addOnPropertiesChangedListener(anyString(), any(), any())); mContext = getInstrumentation().getTargetContext(); spyOn(mContext); @@ -345,11 +379,10 @@ public class SystemServicesTestRule implements TestRule { // Unregister display listener from root to avoid issues with subsequent tests. mContext.getSystemService(DisplayManager.class) .unregisterDisplayListener(mAtmService.mRootWindowContainer); - // The constructor of WindowManagerService registers WindowManagerConstants and - // HighRefreshRateBlacklist with DeviceConfig. We need to undo that here to avoid - // leaking mWmService. - mWmService.mConstants.dispose(); - mWmService.mHighRefreshRateDenylist.dispose(); + + for (int i = mDeviceConfigListeners.size() - 1; i >= 0; i--) { + DeviceConfig.removeOnPropertiesChangedListener(mDeviceConfigListeners.get(i)); + } // This makes sure the posted messages without delay are processed, e.g. // DisplayPolicy#release, WindowManagerService#setAnimationScale. diff --git a/services/tests/wmtests/src/com/android/server/wm/SystemServicesTestRuleTest.java b/services/tests/wmtests/src/com/android/server/wm/SystemServicesTestRuleTest.java index 4056c7195c9b..2e7cc2736410 100644 --- a/services/tests/wmtests/src/com/android/server/wm/SystemServicesTestRuleTest.java +++ b/services/tests/wmtests/src/com/android/server/wm/SystemServicesTestRuleTest.java @@ -16,59 +16,64 @@ package com.android.server.wm; -import static junit.framework.Assert.assertTrue; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertThrows; +import static org.junit.Assert.fail; import android.platform.test.annotations.Presubmit; -import org.junit.Rule; +import com.android.internal.util.GcUtils; + import org.junit.Test; -import org.junit.rules.ExpectedException; import org.junit.runners.model.Statement; -import java.io.IOException; +import java.lang.ref.WeakReference; +import java.util.ArrayList; +import java.util.function.Predicate; @Presubmit public class SystemServicesTestRuleTest { - @Rule - public ExpectedException mExpectedException = ExpectedException.none(); @Test - public void testRule_rethrows_unchecked_exceptions() throws Throwable { - final SystemServicesTestRule mWmsRule = new SystemServicesTestRule(); - Statement statement = new Statement() { - @Override - public void evaluate() throws Throwable { - throw new RuntimeException("A failing test!"); - } - }; - mExpectedException.expect(RuntimeException.class); - mWmsRule.apply(statement, null /* Description*/).evaluate(); + public void testRule_rethrows_throwable() { + assertThrows(Throwable.class, () -> applyRule(rule -> false)); } @Test - public void testRule_rethrows_checked_exceptions() throws Throwable { - final SystemServicesTestRule mWmsRule = new SystemServicesTestRule(); - Statement statement = new Statement() { - @Override - public void evaluate() throws Throwable { - throw new IOException("A failing test!"); + public void testRule_ranSuccessfully() throws Throwable { + final int iterations = 5; + final ArrayList<WeakReference<WindowManagerService>> wmsRefs = new ArrayList<>(); + for (int i = 0; i < iterations; i++) { + applyRule(rule -> { + final WindowManagerService wms = rule.getWindowManagerService(); + assertNotNull(wms); + wmsRefs.add(new WeakReference<>(wms)); + return true; + }); + } + assertEquals(iterations, wmsRefs.size()); + + GcUtils.runGcAndFinalizersSync(); + // Only ensure that at least one instance is released because some references may be kept + // temporally by the message of other thread or single static reference. + for (int i = wmsRefs.size() - 1; i >= 0; i--) { + if (wmsRefs.get(i).get() == null) { + return; } - }; - mExpectedException.expect(IOException.class); - mWmsRule.apply(statement, null /* Description*/).evaluate(); + } + fail("WMS instance is leaked"); } - @Test - public void testRule_ranSuccessfully() throws Throwable { - final boolean[] testRan = {false}; - final SystemServicesTestRule mWmsRule = new SystemServicesTestRule(); - Statement statement = new Statement() { + private static void applyRule(Predicate<SystemServicesTestRule> action) throws Throwable { + final SystemServicesTestRule wmsRule = new SystemServicesTestRule(); + wmsRule.apply(new Statement() { @Override public void evaluate() throws Throwable { - testRan[0] = true; + if (!action.test(wmsRule)) { + throw new Throwable("A failing test!"); + } } - }; - mWmsRule.apply(statement, null /* Description*/).evaluate(); - assertTrue(testRan[0]); + }, null /* description */).evaluate(); } } diff --git a/services/tests/wmtests/src/com/android/server/wm/TaskFragmentTest.java b/services/tests/wmtests/src/com/android/server/wm/TaskFragmentTest.java index 730275cde40b..189a1dacb891 100644 --- a/services/tests/wmtests/src/com/android/server/wm/TaskFragmentTest.java +++ b/services/tests/wmtests/src/com/android/server/wm/TaskFragmentTest.java @@ -149,4 +149,25 @@ public class TaskFragmentTest extends WindowTestsBase { assertEquals(false, info.isEmpty()); assertEquals(activity.token, info.getActivities().get(0)); } + + @Test + public void testActivityVisibilityBehindTranslucentTaskFragment() { + // Having an activity covered by a translucent TaskFragment: + // Task + // - TaskFragment + // - Activity (Translucent) + // - Activity + ActivityRecord translucentActivity = new ActivityBuilder(mAtm) + .setUid(DEFAULT_TASK_FRAGMENT_ORGANIZER_UID).build(); + mTaskFragment.addChild(translucentActivity); + doReturn(true).when(mTaskFragment).isTranslucent(any()); + + ActivityRecord activityBelow = new ActivityBuilder(mAtm).build(); + mTaskFragment.getTask().addChild(activityBelow, 0); + + // Ensure the activity below is visible + mTaskFragment.getTask().ensureActivitiesVisible(null /* starting */, 0 /* configChanges */, + false /* preserveWindows */); + assertEquals(true, activityBelow.isVisibleRequested()); + } } 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 636c6bc77e0a..9304761fc1c9 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 @@ public class TaskTests extends WindowTestsBase { } @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 7dfb5aef7fe7..7cf4b2ebe924 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 @@ public class TestIWindow extends IWindow.Stub { @Override public void resized(ClientWindowFrames frames, boolean reportDraw, MergedConfiguration mergedConfig, boolean forceLayout, boolean alwaysConsumeSystemBars, - int displayId) throws RemoteException { + int displayId, int seqId, int resizeMode) 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 c4547f654c33..7e5d017e2bc4 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 @@ public class TransitionTests extends WindowTestsBase { 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 @@ public class TransitionTests extends WindowTestsBase { 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 10e429250c19..e824f3d2916d 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 @@ public class WindowContainerInsetsSourceProviderTest extends WindowTestsBase { 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 @@ public class WindowContainerInsetsSourceProviderTest extends WindowTestsBase { 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 @@ public class WindowContainerInsetsSourceProviderTest extends WindowTestsBase { 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 @@ public class WindowContainerInsetsSourceProviderTest extends WindowTestsBase { (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 @@ public class WindowContainerInsetsSourceProviderTest extends WindowTestsBase { 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 @@ public class WindowContainerInsetsSourceProviderTest extends WindowTestsBase { 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 @@ public class WindowContainerInsetsSourceProviderTest extends WindowTestsBase { 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 7d2e9bf26b01..ea18e58fe999 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.InsetsVisibilities; 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 @@ public class WindowLayoutTests { 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 @@ public class WindowLayoutTests { 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 class WindowLayoutTests { 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 @@ public class WindowLayoutTests { 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 @@ public class WindowLayoutTests { 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 @@ public class WindowLayoutTests { 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 @@ public class WindowLayoutTests { 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 @@ public class WindowLayoutTests { 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 @@ public class WindowLayoutTests { 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 @@ public class WindowLayoutTests { 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 @@ public class WindowLayoutTests { 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 @@ public class WindowLayoutTests { 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 @@ public class WindowLayoutTests { 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 @@ public class WindowLayoutTests { 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 @@ public class WindowLayoutTests { 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 @@ public class WindowLayoutTests { 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 @@ public class WindowLayoutTests { 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 @@ public class WindowLayoutTests { 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 @@ public class WindowLayoutTests { 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 @@ public class WindowLayoutTests { 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 @@ public class WindowLayoutTests { 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 @@ public class WindowLayoutTests { 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 @@ public class WindowLayoutTests { 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 25d7334a529c..b4d305bbe4d0 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 @@ public class WindowOrganizerTests extends WindowTestsBase { 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 2bebfcac2658..91bde7b31a48 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 @@ public class WindowStateTests extends WindowTestsBase { 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 @@ public class WindowStateTests extends WindowTestsBase { doThrow(new RemoteException("test")).when(win.mClient).resized(any() /* frames */, anyBoolean() /* reportDraw */, any() /* mergedConfig */, anyBoolean() /* forceLayout */, anyBoolean() /* alwaysConsumeSystemBars */, - anyInt() /* displayId */); + anyInt() /* displayId */, anyInt() /* seqId */, anyInt() /* resizeMode */); } catch (RemoteException ignored) { } win.reportResized(); @@ -820,7 +820,6 @@ public class WindowStateTests extends WindowTestsBase { @Test public void testHasActiveVisibleWindow() { final int uid = ActivityBuilder.DEFAULT_FAKE_UID; - mAtm.mActiveUids.onUidActive(uid, 0 /* any proc state */); final WindowState app = createWindow(null, TYPE_APPLICATION, "app", uid); app.mActivityRecord.setVisible(false); @@ -848,6 +847,11 @@ public class WindowStateTests extends WindowTestsBase { // Make the application overlay window visible. It should be a valid active visible window. overlay.onSurfaceShownChanged(true); assertTrue(mAtm.hasActiveVisibleWindow(uid)); + + // The number of windows should be independent of the existence of uid state. + mAtm.mActiveUids.onUidInactive(uid); + mAtm.mActiveUids.onUidActive(uid, 0 /* any proc state */); + assertTrue(mAtm.mActiveUids.hasNonAppVisibleWindow(uid)); } @UseTestDisplay(addWindows = W_ACTIVITY) diff --git a/services/translation/java/com/android/server/translation/TranslationManagerServiceImpl.java b/services/translation/java/com/android/server/translation/TranslationManagerServiceImpl.java index 364d592d7ce0..3833ceb3122e 100644 --- a/services/translation/java/com/android/server/translation/TranslationManagerServiceImpl.java +++ b/services/translation/java/com/android/server/translation/TranslationManagerServiceImpl.java @@ -17,6 +17,7 @@ package com.android.server.translation; import static android.view.translation.TranslationManager.EXTRA_CAPABILITIES; +import static android.view.translation.UiTranslationManager.EXTRA_PACKAGE_NAME; import static android.view.translation.UiTranslationManager.EXTRA_SOURCE_LOCALE; import static android.view.translation.UiTranslationManager.EXTRA_STATE; import static android.view.translation.UiTranslationManager.EXTRA_TARGET_LOCALE; @@ -184,7 +185,7 @@ final class TranslationManagerServiceImpl extends componentName.getPackageName(), 0, userId).uid; } } catch (PackageManager.NameNotFoundException e) { - Slog.d(TAG, "Cannot find packageManager for" + componentName); + Slog.d(TAG, "Cannot find packageManager for" + componentName); } return translationActivityUid; } @@ -192,19 +193,22 @@ final class TranslationManagerServiceImpl extends @GuardedBy("mLock") public void onTranslationFinishedLocked(boolean activityDestroyed, IBinder token, ComponentName componentName) { - int translationActivityUid = + final int translationActivityUid = getActivityUidByComponentName(getContext(), componentName, getUserId()); + final String packageName = componentName.getPackageName(); if (activityDestroyed) { // In the Activity destroy case, we only calls onTranslationFinished() in // non-finisTranslation() state. If there is a finisTranslation() calls by apps, we // should remove the waiting callback to avoid callback twice. - invokeCallbacks(STATE_UI_TRANSLATION_FINISHED, /* sourceSpec= */ - null, /* targetSpec= */null, translationActivityUid); + invokeCallbacks(STATE_UI_TRANSLATION_FINISHED, + /* sourceSpec= */ null, /* targetSpec= */ null, + packageName, translationActivityUid); mWaitingFinishedCallbackActivities.remove(token); } else { if (mWaitingFinishedCallbackActivities.contains(token)) { - invokeCallbacks(STATE_UI_TRANSLATION_FINISHED, /* sourceSpec= */ - null, /* targetSpec= */null, translationActivityUid); + invokeCallbacks(STATE_UI_TRANSLATION_FINISHED, + /* sourceSpec= */ null, /* targetSpec= */ null, + packageName, translationActivityUid); mWaitingFinishedCallbackActivities.remove(token); } } @@ -223,25 +227,25 @@ final class TranslationManagerServiceImpl extends + "state for token=" + token + " taskId=" + taskId + " for state= " + state); return; } + mLastActivityTokens = new WeakReference<>(taskTopActivityTokens); if (state == STATE_UI_TRANSLATION_FINISHED) { mWaitingFinishedCallbackActivities.add(token); } - int translationActivityUid = -1; + IBinder activityToken = taskTopActivityTokens.getActivityToken(); try { - IBinder activityToken = taskTopActivityTokens.getActivityToken(); taskTopActivityTokens.getApplicationThread().updateUiTranslationState( activityToken, state, sourceSpec, targetSpec, viewIds, uiTranslationSpec); - mLastActivityTokens = new WeakReference<>(taskTopActivityTokens); - ComponentName componentName = - mActivityTaskManagerInternal.getActivityName(activityToken); - translationActivityUid = - getActivityUidByComponentName(getContext(), componentName, getUserId()); } catch (RemoteException e) { Slog.w(TAG, "Update UiTranslationState fail: " + e); } + + ComponentName componentName = mActivityTaskManagerInternal.getActivityName(activityToken); + int translationActivityUid = + getActivityUidByComponentName(getContext(), componentName, getUserId()); if (state != STATE_UI_TRANSLATION_FINISHED) { - invokeCallbacks(state, sourceSpec, targetSpec, translationActivityUid); + invokeCallbacks(state, sourceSpec, targetSpec, componentName.getPackageName(), + translationActivityUid); } } @@ -255,7 +259,7 @@ final class TranslationManagerServiceImpl extends try (TransferPipe tp = new TransferPipe()) { activityTokens.getApplicationThread().dumpActivity(tp.getWriteFd(), activityTokens.getActivityToken(), prefix, - new String[] { + new String[]{ Activity.DUMP_ARG_DUMP_DUMPABLE, UiTranslationController.DUMPABLE_NAME }); @@ -266,20 +270,24 @@ final class TranslationManagerServiceImpl extends pw.println(prefix + "Got a RemoteException while dumping the activity"); } } else { - pw.print(prefix); pw.println("No requested UiTranslation Activity."); + pw.print(prefix); + pw.println("No requested UiTranslation Activity."); } final int waitingFinishCallbackSize = mWaitingFinishedCallbackActivities.size(); if (waitingFinishCallbackSize > 0) { - pw.print(prefix); pw.print("number waiting finish callback activities: "); + pw.print(prefix); + pw.print("number waiting finish callback activities: "); pw.println(waitingFinishCallbackSize); for (IBinder activityToken : mWaitingFinishedCallbackActivities) { - pw.print(prefix); pw.print("activityToken: "); pw.println(activityToken); + pw.print(prefix); + pw.print("activityToken: "); + pw.println(activityToken); } } } private void invokeCallbacks( - int state, TranslationSpec sourceSpec, TranslationSpec targetSpec, + int state, TranslationSpec sourceSpec, TranslationSpec targetSpec, String packageName, int translationActivityUid) { Bundle res = new Bundle(); res.putInt(EXTRA_STATE, state); @@ -288,6 +296,7 @@ final class TranslationManagerServiceImpl extends res.putSerializable(EXTRA_SOURCE_LOCALE, sourceSpec.getLocale()); res.putSerializable(EXTRA_TARGET_LOCALE, targetSpec.getLocale()); } + res.putString(EXTRA_PACKAGE_NAME, packageName); // TODO(177500482): Only support the *current* Input Method. List<InputMethodInfo> enabledInputMethods = LocalServices.getService(InputMethodManagerInternal.class) @@ -299,6 +308,7 @@ final class TranslationManagerServiceImpl extends } catch (RemoteException e) { Slog.w(TAG, "Failed to invoke UiTranslationStateCallback: " + e); } + return; } // Code here is non-optimal since it's temporary.. boolean isIme = false; diff --git a/services/usage/java/com/android/server/usage/UsageStatsService.java b/services/usage/java/com/android/server/usage/UsageStatsService.java index b9abbf09e74d..366ab0968bb8 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 @@ public class UsageStatsService extends SystemService implements == 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 @@ public class UsageStatsService extends SystemService implements 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 class UsageStatsService extends SystemService implements 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 @@ public class UsageStatsService extends SystemService implements @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 @@ public class UsageStatsService extends SystemService implements 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 @@ public class UsageStatsService extends SystemService implements 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 class UsageStatsService extends SystemService implements 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 a70b033237cf..dd58d3879bb2 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 @@ public class UsbHostManager { // 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 24ce7e76a49c..c8bcb83cae74 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 @@ public class SoundTriggerHelper implements SoundTrigger.StatusListener { 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 @@ public class SoundTriggerHelper implements SoundTrigger.StatusListener { } if (!event.recognitionStillActive) { - model.setStopped(); + model.setStoppedLocked(); } try { @@ -918,7 +921,7 @@ public class SoundTriggerHelper implements SoundTrigger.StatusListener { 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 @@ public class SoundTriggerHelper implements SoundTrigger.StatusListener { } if (!event.recognitionStillActive) { - modelData.setStopped(); + modelData.setStoppedLocked(); } try { @@ -1200,7 +1203,7 @@ public class SoundTriggerHelper implements SoundTrigger.StatusListener { 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 @@ public class SoundTriggerHelper implements SoundTrigger.StatusListener { 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 @@ public class SoundTriggerHelper implements SoundTrigger.StatusListener { 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 @@ public class SoundTriggerHelper implements SoundTrigger.StatusListener { 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 @@ public class SoundTriggerHelper implements SoundTrigger.StatusListener { // 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 @@ public class SoundTriggerHelper implements SoundTrigger.StatusListener { 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 @@ public class SoundTriggerHelper implements SoundTrigger.StatusListener { 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 @@ public class SoundTriggerHelper implements SoundTrigger.StatusListener { mRecognitionConfig = null; mRequested = false; mCallback = null; + notifyAll(); } synchronized void clearCallback() { @@ -1675,4 +1691,12 @@ public class SoundTriggerHelper implements SoundTrigger.StatusListener { 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 5a95210c3c46..d527a230a97b 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.CAPTURE_AUDIO_HOTWORD; 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.PersistableBundle; 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 @@ final class HotwordDetectionConnection { 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 @@ final class HotwordDetectionConnection { // 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 @@ final class HotwordDetectionConnection { private IMicrophoneHotwordDetectionVoiceInteractionCallback mSoftwareCallback; private Instant mLastRestartInstant; - private ScheduledFuture<?> mCancellationTaskFuture; private ScheduledFuture<?> mCancellationKeyPhraseDetectionFuture; private ScheduledFuture<?> mDebugHotwordLoggingTimeoutFuture = null; @@ -196,16 +206,20 @@ final class HotwordDetectionConnection { 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 @@ final class HotwordDetectionConnection { 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 @@ final class HotwordDetectionConnection { 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 @@ final class HotwordDetectionConnection { } 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 837cf8b28ff8..dda5ea7aab53 100644 --- a/telephony/java/android/telephony/CarrierConfigManager.java +++ b/telephony/java/android/telephony/CarrierConfigManager.java @@ -504,7 +504,12 @@ public class CarrierConfigManager { /** 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"; /** @@ -8488,8 +8493,9 @@ public class CarrierConfigManager { * <item value="source=GERAN|UTRAN, target:IWLAN, type=disallowed"/> * <!-- Handover from IWLAN to 3G/4G/5G is not allowed if the device is roaming. --> * <item value="source=IWLAN, target=UTRAN|EUTRAN|NGRAN, roaming=true, type=disallowed"/> - * <!-- Handover from 4G to IWLAN is not allowed --> - * <item value="source=EUTRAN, target=IWLAN, type=disallowed"/> + * <!-- Handover from 4G to IWLAN is not allowed if the device has capability in either IMS + * or EIMS--> + * <item value="source=EUTRAN, target=IWLAN, type=disallowed, capabilities=IMS|EIMS"/> * <!-- Handover is always allowed in any condition. --> * <item value="source=GERAN|UTRAN|EUTRAN|NGRAN|IWLAN, * target=GERAN|UTRAN|EUTRAN|NGRAN|IWLAN, type=allowed"/> @@ -8594,7 +8600,7 @@ public class CarrierConfigManager { 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 5ef22de1dab3..f3139a70eade 100644 --- a/telephony/java/android/telephony/TelephonyManager.java +++ b/telephony/java/android/telephony/TelephonyManager.java @@ -8352,24 +8352,6 @@ public class TelephonyManager { } /** - * 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 @@ public class TelephonyManager { @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 @@ public class TelephonyManager { @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 fc94ebf2cc37..8143da5ad431 100644 --- a/telephony/java/android/telephony/data/ApnSetting.java +++ b/telephony/java/android/telephony/data/ApnSetting.java @@ -549,7 +549,6 @@ public class ApnSetting implements Parcelable { * 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 @@ public class ApnSetting implements Parcelable { /** * 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 @@ public class ApnSetting implements Parcelable { 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 892eb2937491..bd346d516a1d 100644 --- a/telephony/java/android/telephony/data/DataService.java +++ b/telephony/java/android/telephony/data/DataService.java @@ -31,6 +31,7 @@ import android.os.IBinder; 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 @@ public abstract class DataService extends Service { * 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 @@ public abstract class DataService extends Service { * 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 @@ public abstract class DataService extends Service { * 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 @@ public abstract class DataService extends Service { * </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 fe4453081362..5ffee5638cfa 100644 --- a/telephony/java/android/telephony/data/EpsBearerQosSessionAttributes.java +++ b/telephony/java/android/telephony/data/EpsBearerQosSessionAttributes.java @@ -32,7 +32,12 @@ import java.util.List; 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 dc96b3585864..e3ebb9a23950 100644 --- a/telephony/java/com/android/internal/telephony/ITelephony.aidl +++ b/telephony/java/com/android/internal/telephony/ITelephony.aidl @@ -978,14 +978,6 @@ interface ITelephony { 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 @@ interface ITelephony { * 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 35f1e585931b..644d450a7a88 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.net.SntpClient; 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.InetAddress; 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 @@ public class BandwidthEnforcementTestService extends IntentService { 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/SoundTriggerTestApp/OWNERS b/tests/SoundTriggerTestApp/OWNERS index 816bc6bba639..9db19a37812b 100644 --- a/tests/SoundTriggerTestApp/OWNERS +++ b/tests/SoundTriggerTestApp/OWNERS @@ -1 +1,2 @@ include /core/java/android/media/soundtrigger/OWNERS +mdooley@google.com diff --git a/tests/TrustTests/AndroidManifest.xml b/tests/TrustTests/AndroidManifest.xml index 68bc1f69628f..8b4cbfd0e44b 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 790afd389152..af7a98c22ad1 100644 --- a/tests/TrustTests/src/android/trust/test/GrantAndRevokeTrustTest.kt +++ b/tests/TrustTests/src/android/trust/test/GrantAndRevokeTrustTest.kt @@ -60,7 +60,6 @@ class GrantAndRevokeTrustTest { @Test fun sleepingDeviceWithoutGrantLocksDevice() { uiDevice.sleep() - await() lockStateTrackingRule.assertLocked() } @@ -69,7 +68,6 @@ class GrantAndRevokeTrustTest { fun grantKeepsDeviceUnlocked() { trustAgentRule.agent.grantTrust(GRANT_MESSAGE, 10000, 0) uiDevice.sleep() - await() lockStateTrackingRule.assertUnlocked() } @@ -80,7 +78,6 @@ class GrantAndRevokeTrustTest { 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 8f200a64450e..a7dd41ad2e98 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.trust.test.lib.TrustAgentRule 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 @@ class LockUserTest { 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 000000000000..14c227b1f678 --- /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 0023af8893e2..834f2122a21b 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 @@ class LockStateTrackingRule : TestRule { } } - 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 000000000000..1395c5f2e635 --- /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 000000000000..7f4ee1d617fa --- /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 000000000000..190df819dd64 --- /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 000000000000..863f976b8aff --- /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 000000000000..f9595bdad9cf --- /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 000000000000..c2bbddcb5668 --- /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 000000000000..81bf235fe0a6 --- /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/tools/traceinjection/test/com/android/traceinjection/Trace.java b/tools/traceinjection/test/com/android/traceinjection/Trace.java new file mode 100644 index 000000000000..9e1c545673e8 --- /dev/null +++ b/tools/traceinjection/test/com/android/traceinjection/Trace.java @@ -0,0 +1,22 @@ +/* + * 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; + +public @interface Trace { + long tag(); + String label() default ""; +} diff --git a/tools/validatekeymaps/Android.bp b/tools/validatekeymaps/Android.bp index 0423b7abd685..ff24d160b917 100644 --- a/tools/validatekeymaps/Android.bp +++ b/tools/validatekeymaps/Android.bp @@ -32,7 +32,7 @@ cc_binary_host { "libui-types", ], target: { - linux_glibc: { + host_linux: { static_libs: [ // libbinder is only available for linux "libbinder", |